iOS锁

115 阅读2分钟

锁是用来保证线程安全同步工具,当一个线程在访问数据或资源前,需要先获取锁,如果此时该资源以被上锁,则该线程只能等待知道资源的锁被释放掉。

atomic并不能保证数据的安全,举个例子。

定义了一个数组属性arr(atomic):

//Thread A

for(int i = 0 ; i < 1000 ; i++){

     if(i%2 == 0){

          self.arr = @[@"1",@"2",@"3"];

     }else{

          self.arr = @[@"4",@"5"];     

     }

}

//Thread B

if(self.arr.count > 2){

     NSString *str = [self.arr objectAtIndex:1];

}

虽然此时判断了数组长度大于2,大家可能觉得拿到的结果一定是2,但是有可能是5,因为线程A和B可能是同步的,此时便需要对self.arr加锁。

锁的分类:

自旋锁:

在线程等待时会一直轮询,处于忙等状态。但是减少了线程切换的开销。

自旋锁是不安全的,可能会出现忙等,因为优先级反转问题。什么是优先级反转,举个例子:

任务A(高优先级)现在需要访问资源Z;

此时任务C(低优先级)现在已经对资源Z上锁了,但是此时没有获取到时间片执行任务;

因为此时任务B(中优先级)占用着时间片在执行任务;

那么问题来了,当任务B执行完之后,C和A就会去抢占时间片执行任务,但是A的时间片比C的高,那么A获得时间片,他也没干啥正经事,一直轮询C的锁是否释放掉;

而C也一直在等待A把时间片交还给他,那么死循环就出现了。

解决优先级反转的方案:

1.优先级继承:

占有锁的任务可以继承等待该锁的线程最高优先级,这样就拥有了最高优先级,一旦时间片空闲,就可以获得时间片开始执行任务;

2.优先级天花板

给临界区设置一个最高优先级,一旦进入该临界区,那么将获得最高优先级。

3.禁止中断

只存在两种优先级,一种是可被抢占的,一种是禁止中断的。

进入临界区优先级为禁止中断的,其他的都是可被抢占的,就不存在互抢了。

互斥锁:互斥锁可分为递归和非递归锁

@synchonized:递归锁

NSLock:非递归锁

NSConditionLock条件锁,只有condition参数和初始化的condition相等,lock才能正确的进行加锁操作。