多线程 - 线程锁(互斥锁、信号量、自旋锁)

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);//解锁
上一篇下一篇

猜你喜欢

热点阅读