iOS中的线程同步方案:
1.OSSpinLock:
叫做“自旋锁”,等待锁的线程会处于忙等(busy-wait)状态,一直占用CPU资源
目前已经不再安全,可能会出现优先级反转问题(ios10之后就不适用)。
如果等待它的线程优先级比较高,他会一直占用着CPU资源,优先级低的线程就无法释放锁。
导入头文件#import <libkern/OSAtomic.h>
OSSpinLock lock = OS_SPINLOCK_INIT; //初始化
bool result = OSSpinLockTry(&lock); //尝试加锁(如果需要等待就不加锁,直接返回false;如果不需要等待就加锁,返回true)
OSSpinLockLock(&lock); //加锁
OSSpinLockUnlock(&lock); //解锁
1)引入头文件:#import <libkern/OSAtomic.h>
2)定义全局变量,初始化:
3)使用加锁解锁
存钱取钱加锁实现:
2.os_unfair_lock
os_unfair_lock用于取代不安全的OSSpinLock,从iOS10开始才支持。
从底层调用看,等待os_unfair_lock锁的线程会处于休眠状态,并非忙等。
需要导入头文件#import <os/lock.h>
属于低级锁 low-level-lock
(个人理解:从底层一步一步走,发现它会进入休眠,所以属于互斥锁)
3.pthread_mutex
mutex叫做“互斥锁”,等待锁的线程会处于休眠状态。
需要导入头文件#import <pthread.h>
默认属性PTHREAD_MUTEX_DEFAULT是默认锁,换成PTHREAD_MUTEX_RECURSIVE为递归锁
递归锁:允许同一个线程对一把锁进行重复加锁
pthread_mutex-条件:多线程相互依赖的场景可能会使用(生产者、消费者模式)
4.dispatch_semaphore
semaphore叫做“信号量”
信号量的初始值,可以用来控制线程并发访问的最大数量。
信号量的初始值为1,代表同时只允许1条线程访问资源,保证线程同步。
5.dispatch_queue(DISPATCH_QUEUE_SERIAL)
直接使用GCD的串行队列,也可以实现线程同步。
6.NSLOCK
是对mutex普通锁的封装
7.NSRecursiveLock
NSRecursiveLock也是对mutex递归锁对封装,API跟NSLock基本一致。
8.NSCondition
NSCondition是对mutex和cond的封装。
9.NSConditionLock
NSConditionLock是对NSCondition的进一步封装,可以设置具体的条件值。
这样可以设置让线程之间依赖
10.@synchronized
性能从高到低:推荐使用dispatch_semaphore、pthread_mutex
自旋锁、互斥锁比较
什么时候使用自旋锁比较好?
预计线程等待锁的时间很短;
加锁的代码(临界区(lock与unlock之间))经常被调用,但竞争情况很少发生;
CPU资源不紧张;
多核处理器;
什么时候使用互斥锁比较好?
预计线程等待锁的时间较长;
单核处理器;
临界区有IO操作(文件操作);
临界区代码复制或者循环量大;
临界区竞争非常激烈;
网友评论