多线程安全问题及各种锁
多线程使用不当会出现资源竞争,比如多个线程同时对一块资源进行修改,就会很容易引发数据错乱和数据安全问题。
示例:
以购票系统为例,
对于多线程出现的这种问题,我们的解决办法就是使用线程同步技术,而常见的就是加锁。
2.1 OSSpinLock 自旋锁
自旋锁等待锁的线程会处于忙等(busy-wait)状态,一直占用着CPU资源。
并且现在已经不安全,可能出现优先级反转的问题。
如果等待锁的优先级较高,它会一直占用着CPU的资源,优先级低的线程就无法释放锁。
在iOS10被苹果废弃。由于已经不再安全, 这里不讨论用法了.
2.2 os_unfair_lock
导入头文件 #import <os/lock.h>
调用 ticketTest 方法
打印结果:
2.3 pthread_mutex 互斥锁
普通用法
导入头文件 #import <pthread.h>
调用 ticketTest 方法
打印结果:
mutex 也叫“互斥锁”,等待锁的线程处于休眠状态,不是忙等状态。
上面使用的是 Normal 类型同 OSSpinLock 和 os_unfair_lock 作用一样
递归用法
递归锁在被同一线程重复获取时不会产生死锁
递归类型 PTHREAD_MUTEX_RECURSIVE :
条件用法
2.4 NSLock、NSRecursiveLock
NSLock 是对 mutex 普通锁的封装
NSRecursiveLock 是对 mutex 递归锁的封装
调用 ticketTest 方法
打印结果:
NSRecursiveLock 用法与 NSLock 的用法一样。
2.5 NSCondition
NSCondition 是对 mutex 和 cond 的封装
2.6 NSConditionLock
它是对 NSCondition 的进一步封装,可以设置具体的条件值
2.7 dispatch_queue
直接使用GCD的串行队列,也可以实现线程同步
调用ticketTest方法
打印结果:
2.8 dispatch_semaphore
信号量的初始值可以控制线程并发访问的最大值
初始值为1时,代表同时只允许1条线程访问资源,保证线程的同步
调用otherTest会发现每隔两秒打印5条信息。
2.9 @synchronized
是对mutex的递归锁的封装,源码objc4中的objc-sync.mm文件查看
@synchronized(obj)内部会生成obj对应的递归锁,然后进行加锁解锁操作
本文来自: 旺仔大包子
推荐上篇文章: iOS多线程之NSOperation的使用