1.概念:
锁的概念:
锁是最常用的同步工具。一段代码段在同一个时间只能允许被一个线程访问,比如一个线程A进入加锁代码之后由于已经加锁,另一个线程B就无法访问,只有等待前一个线程A执行完加锁代码后解锁,B线程才能访问加锁代码。不要将过多的其他操作代码放到里面,否则一个线程执行的时候另一个线程就一直在等待,就无法发挥多线程的作用了。
使用场景:多线程操作同一个对象的时候就需要加锁。和同步异步没有关系,只要可能不在一个线程就需要,当然,我们大部分操作都是在主线程的
2.加锁的方法:
1.NSLock
在Cocoa程序中NSLock中实现了一个简单的互斥锁,实现了NSLocking protocol。
lock,加锁
unlock,解锁
tryLock,尝试加锁,如果失败了,并不会阻塞线程,只是立即返回
NOlockBeforeDate:,在指定的date之前暂时阻塞线程(如果没有获取锁的话),如果到期还没有获取锁,则线程被唤醒,函数立即返回NO
使用tryLock并不能成功加锁,如果获取锁失败就不会执行加锁代码了。
2.@synchronized代码块
3.
条件信号量dispatch_semaphore_t
4.条件锁NSCondition
5.条件锁NSConditionLock :也有人说这是个互斥锁
NSConditionLock同样实现了NSLocking协议,试验过程中发现性能很低。
6.递归锁NSRecursiveLock :有时候“加锁代码”中存在递归调用,递归开始前加锁,递归调用开始后会重复执行此方法以至于反复执行加锁代码最终造成死锁,这个时候可以使用递归锁来解决。使用递归锁可以在一个线程中反复获取锁而不造成死锁,这个过程中会记录获取锁和释放锁的次数,只有最后两者平衡锁才被最终释放
3.总结:
@synchronized:适用线程不多,任务量不大的多线程加锁
NSLock:其实NSLock并没有想象中的那么差,不知道大家为什么不推荐使用
dispatch_semaphore_t:使用信号来做加锁,性能提升显著
NSCondition:使用其做多线程之间的通信调用不是线程安全的
NSConditionLock:单纯加锁性能非常低,比NSLock低很多,但是可以用来做多线程处理不同任务的通信调用
NSRecursiveLock:递归锁的性能出奇的高,但是只能作为递归使用,所以限制了使用场景
NSDistributedLock:因为是MAC开发的,就不讨论了
POSIX(pthread_mutex):底层的api,复杂的多线程处理建议使用,并且可以封装自己的多线程
OSSpinLock:性能也非常高,可惜出现了线程问题
dispatch_barrier_async/dispatch_barrier_sync:测试中发现dispatch_barrier_sync比dispatch_barrier_async性能要高,真是大出意外
代码例子:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let obj = TestObj.init()
let lock = NSLock.init()
//只在异步多线程里面能看到效果,同步的时候没看到效(加锁和没加锁一个效果)
let globalQueue = DispatchQueue.global()
globalQueue.async {
print("1111")
lock.lock()
obj.firstMethod()
sleep(10) //线程1执行挂起10秒
lock.unlock()
}
globalQueue.async {
print("2222")
lock.lock()
obj.secondMethod()
sleep(1) //线程1执行挂起2秒
lock.unlock()
}
globalQueue.async {
print("3333")
lock.lock()
obj.thirdMethod()
sleep(1) //线程1执行挂起2秒
lock.unlock()
}
globalQueue.async {
print("4444")
lock.lock()
obj.fourthMethod()
sleep(1) //线程1执行挂起2秒
lock.unlock()
}
globalQueue.async {
// @synchronized(self) { oc中的使用
// //需要执行的代码块
// }
// objc_sync_enter(obj) swift中的写法
//
// objc_sync_exit(obj)
print("5555")
lock.lock()
// objc_sync_enter(obj)
obj.fiveMethod()
sleep(1) //线程1执行挂起2秒
// objc_sync_exit(obj)
lock.unlock()
}
}
class TestObj: NSObject {
override init() {
}
func firstMethod() {
print("方法1111")
}
func secondMethod() {
print("方法2222")
}
func thirdMethod() {
print("方法3333")
}
func fourthMethod() {
print("方法4444")
}
func fiveMethod() {
print("方法5555")
}
}