多线程 - 线程锁(互斥锁、信号量、自旋锁)
2021-02-28 本文已影响0人
Th丶小伟
互斥锁
互斥锁:被持有的状态下,其他资源申请者只能进入休眠状态,当锁被释放后,CPU会唤醒资源申请者,然后获得锁并访问资源
NSLock
常用方法:lock加锁 unlock解锁。
- (BOOL)tryLock; 尝试加锁 不可用时(被锁了),会返回NO,不会阻塞线程
- (BOOL)lockBeforeDate:(NSDate *)limit; 在所指定Date之前尝试加锁,如果在指定时间之前不能加锁则返回NO。
self.lock = [NSLock new];
[self.lock lock];
[self.lock unlock];
synchronized
@synchronized块会隐式的添加一个异常处理例程来保护代码,该处理例程会在异常抛出的时候自动的释放互斥锁
比较耗费性能。不是线程安全。
for循环一下代码 1000次
会崩溃。不同线程获取的对象不同
@synchronized (_testArray) {
if (_testArray.count == 0) {
NSMutableArray *array = [NSMutableArray array];
_testArray = array;
}
}
GCD - 信号量
定义:用来控制访问资源的数量标识,控制访问的数量。线程的调度
信号量为0则等待 任务执行完毕则加一。执行一个任务则减一
//创建信号量,参数:信号量的初值,如果小于0则会返回NULL
dispatch_semaphore_create(信号量值)
//等待降低信号量
dispatch_semaphore_wait(信号量,等待时间)
//提高信号量
dispatch_semaphore_signal(信号量)
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
//线程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"线程1开始");
sleep(5);
NSLog(@"线程1结束");
dispatch_semaphore_signal(semaphore);
});
//线程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"线程2开始");
sleep(5);
NSLog(@"线程2结束");
dispatch_semaphore_signal(semaphore);
});
自旋锁
定义:线程反复检查锁变量是否可用,忙等状态(忙碌等待)。
OSSpinLock不在是线程安全。有潜在的优先级反转,使用os_unfair_lock
#import <os/lock.h>
@property (nonatomic, assign) os_unfair_lock unfair_lock;
self.unfair_lock = OS_UNFAIR_LOCK_INIT;//创建自旋锁
os_unfair_lock_lock(&_unfair_lock);//加锁
os_unfair_lock_unlock(&_unfair_lock);//解锁