iOS读写锁三种方案实现对比

219 阅读2分钟

关于iOS读写锁,三种实现方案对比,第三种实现方案会造成写饥饿

一.系统读写锁

class LockTest {
    private let queue = DispatchQueue(label: "com.concurrent.queue",attributes: .concurrent)
    private var rwlock:pthread_rwlock_t
    init() {
        rwlock = pthread_rwlock_t()
        pthread_rwlock_init(&rwlock, nil)
    }   
   
    public func testPThreadRWLock() {
        readThread(num: 1)
        readThread(num: 2)
        writeThread(num: 1)
        readThread(num: 3)
        readThread(num: 4)
        writeThread(num: 2)
        readThread(num: 5)
        readThread(num: 6)
        writeThread(num: 3)
        readThread(num: 7)
        readThread(num: 8)
        readThread(num: 9)
        writeThread(num: 4)
        readThread(num: 10)
        readThread(num: 11)
        readThread(num: 12)
        writeThread(num: 5)
        readThread(num: 13)
    }
   
    private func readThread(num:Int) {
        queue.async {
            pthread_rwlock_rdlock(&self.rwlock)
            Thread.sleep(forTimeInterval: 1)
            print("read\(num)")
            pthread_rwlock_unlock(&self.rwlock)
        }
    }
   
    private func writeThread(num:Int) {
        queue.async {
            pthread_rwlock_wrlock(&self.rwlock)
            Thread.sleep(forTimeInterval: 1)
            print("write\(num)")
            pthread_rwlock_unlock(&self.rwlock)
        }
    }
}

let lockTest:LockTest = LockTest()
lockTest.testPThreadRWLock()

输出结果

read1
read2
write1
read3
read4
write2
read5
read6
write3
read8
read7
read9
write4
read11
read10
read12
write5
read13

二.GCD barrierAsync

class LockTest {
    private let queue = DispatchQueue(label: "com.concurrent.queue",attributes: .concurrent)
    public func testBarrierRWLock() {
        readThread(num: 1)
        readThread(num: 2)
        writeThread(num: 1)
        readThread(num: 3)
        readThread(num: 4)
        writeThread(num: 2)
        readThread(num: 5)
        readThread(num: 6)
        writeThread(num: 3)
        readThread(num: 7)
        readThread(num: 8)
    }

    private func readThread(num:Int) {
        queue.async {
            Thread.sleep(forTimeInterval: 0.2)
            print("read\(num)")
        }
    }

    private func writeThread(num:Int) {
        queue.async(flags: .barrier) {
            Thread.sleep(forTimeInterval: 0.2)
            print("write\(num)")
        }
    }
}

let lockTest:LockTest = LockTest()
lockTest.testBarrierRWLock()

输出

read1
read2
write1
read3
read4
write2
read5
read6
write3
read8
read7

三.自定义实现读写锁

class CustomRWLock {
    //读数量
    private var readCount:Int = 0
    //读锁
    private var rlock:NSLock = NSLock()
    //写锁
    private var wlock:NSLock = NSLock()

    public func rdLock(){
        rlock.lock()
        if readCount == 0 {
            wlock.lock()
        }
        readCount = readCount + 1
        rlock.unlock()
    }
    
    public func wrLock(){
        wlock.lock()
    }
    
    public func rdUnlock(){
        rlock.lock()
        readCount = readCount - 1
        if readCount == 0 {
            wlock.unlock()
        }
        rlock.unlock()
    }
    
    public func wrUnlock(){
        wlock.unlock()
    }
}

class LockTest {
    private let queue = DispatchQueue(label: "com.concurrent.queue",attributes: .concurrent)
    private var custRwLock:CustomRWLock = CustomRWLock()
    public func testCustomRWLock(){
        readThread(num: 1)
        readThread(num: 2)
        writeThread(num: 1)
        readThread(num: 3)
        readThread(num: 4)
        writeThread(num: 2)
        readThread(num: 5)
        readThread(num: 6)
        writeThread(num: 3)
        readThread(num: 7)
        readThread(num: 8)
        writeThread(num: 4)
        readThread(num: 9)
        readThread(num: 10)
        writeThread(num: 5)
        readThread(num: 11)
        readThread(num: 12)
    }
    
    private func readThread(num:Int) {
        queue.async {
            self.custRwLock.rdLock()
            Thread.sleep(forTimeInterval: 1)
            print("read\(num)")
            self.custRwLock.rdUnlock()
        }
    }

    private func writeThread(num:Int) {
        queue.async {
            self.custRwLock.wrLock()
            Thread.sleep(forTimeInterval: 1)
            print("write\(num)")
            self.custRwLock.wrUnlock()
        }
    }
}

let lockTest:LockTest = LockTest()
lockTest.testCustomRWLock()

输出:

read1
read3
read10
read7
read6
read8
read9
read11
read2
read4
read5
read12
write1
write2
write3
write4
write5
推荐文档:
  1. zhuanlan.zhihu.com/p/91408261 Java 读写锁ReentrantReadWriteLock,注意ReentrantReadWriteLock内部实现了公平与非公平两种特性
  2. www.cnblogs.com/fortunely/p… C++读写锁,写优先,读可能饥饿问题