iOS中自旋锁和互斥锁
起因
属性修饰符atomic,是否是绝对线程安全的?
当然乍一看,这两个问题好像没有必然的联系,但是了解atomic的内部实现,就能明白为什么我能跨度到自旋锁和互斥锁。(因为atomic其实内部是对于setter和getter加锁实现的)
后边我们再看atomic到底是否安全的问题
定义
锁:在计算机科学中,锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的满足。(维基百科中的定义)
自旋锁: 自旋锁其实就是线程再未获得锁的时候处于忙等的状态,一直消耗cpu,而不会进入内核态。
互斥锁:互斥锁则是当未获得锁时,线程进入内核态,释放cpu的消耗,直到锁资源被释放,重新唤起休眠的线程。
其实从定义中我们也能很明确的看到了他们的优缺点:自旋锁一直处于忙等的状态,会持续消耗cpu,而互斥锁则不会,但是互斥锁会频繁的切换线程的状态,比较效率上会比自旋锁低很多。
iOS 中的锁
- NSLock 非递归互斥锁。是对于pthread_mutex_t的封装。遵循了NSLocking协议。-lock与unlock必须在同一线程调用,否则会产生问题。
- NSCondition, 与NSLock类似都是对于pthread_mutex_t的封装,区别在于,他还对于pthread_cond_t的封装,所以NSLock只能等待锁资源释放,然后唤起等待的线程,而NSCondition则可以由我们主动唤起线程
- NSConditionLock, 条件互斥锁,也就是说,除了正常的锁资源释放我们获得锁之外,我们还需要满足设置的另外一个条件,才能获得锁。释放锁也是如此。
- NSRecursiveLock, 递归锁,也是一个互斥锁。与其他锁不同的是,递归锁可以其他锁如果同一个线程获得锁并且没有释放,这个线程再次获取锁就会造成死锁,互斥锁则可以运行同一个线程获得了锁之后依然可以再次获得锁。
- @synchronize,对象锁,也是一个递归互斥锁。
- Dispatch_semaphore, 信号量,更高级的互斥锁,初始值可以控制并发访问的最大量
- OSSpinLock, iOS 10 废弃的自旋锁,原因是10之后增加了许多的线程默认优先级,自旋锁可能会造成线程优先级反转,导致死锁
- os_unfair_lock, 用来取代OSSpinLock的互斥锁
- pthread_mutex, 底层pthread互斥锁
性能
从ibireme的博客中图来看性能对比大概是这样的:
当然作者只是单线程的一个时间消耗数据。不能反应多线程的实际性能,只能作为一个定性分析。