定义
互斥锁:
NSLock互斥量只允许一个线程同时执行一个任务。也就是同一个程获取,同一个线程释放。
递归锁:
NSRecursiveLock类定义的锁可以在同一线程多次lock,而不会造成死锁。递归锁会跟踪它被多少次lock。每次成功的lock都必须平衡调用unlock操作。只有所有的锁住和解锁操作都平衡的时候,锁才真正被释放给其他线程获得。
区别:
互斥锁可以分为非递归锁/递归锁两种,主要区别在于:同一个线程可以重复获取递归锁,不会死锁; 同一个线程重复获取非递归锁,则会产生死锁。
代码:
如下代码,如果使用互斥锁,则会死锁,因为在同一个线程多次调用了lock而未调用同等次数的unlock
let lock = NSLock()
let queue = DispatchQueue.init(label: "RyukieQ", qos: .default, attributes: .concurrent, autoreleaseFrequency: .workItem, target: nil)
func testLog1(times: Int) {
lock.lock() // 不断递归加锁
print("\(times) 线程: \(Thread.current)")
if times > 0 {
testLog1(times: times - 1)
}
lock.unlock()
}
func demo() {
for _ in 0..<10 {
queue.async {
// self.lock.lock() // 不断递归加锁
self.testLog1(times: 10)
// self.lock.unlock()
}
}
}
demo()
上描的例子会造成死锁,在递归的函数内调用了lock,在同一个线程多次调用了lock而未调用同等次数的unlock。
那么如下代码会不会死锁呢?
func testLog1(times: Int) {
lock1.lock() // 不断递归加锁
print("\(times) 线程: \(Thread.current)")
testLog2(times: times)
lock1.unlock()
}
func testLog2(times: Int) {
lock1.lock() // 不断递归加锁
print("2 \(times) 线程: \(Thread.current)")
lock1.unlock()
}
func demo() {
for _ in 0..<10 {
queue.async {
// self.lock1.lock() // 不断递归加锁
self.testLog1(times: 10)
// self.lock1.unlock()
}
}
}
答案也会造成死锁,虽然不是在递归函数内调用,但是还是在同一个线程多次调用了lock而未调用同等次数的unlock。故还是会造成死锁。
参考
- https://juejin.cn/post/7007983045345034247
- https://cloud.tencent.com/developer/article/1037807