iOS 开发中的八种锁(Lock)

iOS 开发中的八种锁(Lock)_第1张图片

锁 是什么意思?

我们在使用多线程的时候多个线程可能会访问同一块资源,这样就很容易引发数据错乱和数据安全等问题,这时候就需要我们保证每次只有一个线程访问这一块资源, 应运而生。

OSSpinLock2

在 OSSpinLock1 图中可以发现:当我们锁住线程1时,在同时锁住线程2的情况下,线程2会一直等待(自旋锁不会让等待的进入睡眠状态),直到线程1的任务执行完且解锁完毕,线程2会立即执行;而在 OSSpinLock2 图中,因为我们注释掉了线程1中的解锁代码,会绕过线程1,直到调用了线程2的解锁方法才会继续执行线程1中的任务,正常情况下,lock和unlock最好成对出现

这里顺便提一下trylock和lock使用场景:

当前线程锁失败,也可以继续其它任务,用 trylock 合适

当前线程只有锁成功后,才会做一些有意义的工作,那就 lock,没必要轮询 trylock

dispatch_semaphore 信号量

dispatch_semaphore_create(1): 传入值必须 >=0, 若传入为 0 则阻塞线程并等待timeout,时间到后会执行其后的语句

dispatch_semaphore_wait(signal, overTime):可以理解为 lock,会使得 signal 值 -1

dispatch_semaphore_signal(signal):可以理解为 unlock,会使得 signal 值 +1


停车场剩余4个车位,那么即使同时来了四辆车也能停的下。如果此时来了五辆车,那么就有一辆需要等待。

信号量的值(signal)就相当于剩余车位的数目,dispatch_semaphore_wait 函数就相当于来了一辆车,dispatch_semaphore_signal 就相当于走了一辆车。停车位的剩余数目在初始化的时候就已经指明了(dispatch_semaphore_create(long value)),调用一次 dispatch_semaphore_signal,剩余的车位就增加一个;调用一次dispatch_semaphore_wait 剩余车位就减少一个;当剩余车位为 0 时,再来车(即调用 dispatch_semaphore_wait)就只能等待。有可能同时有几辆车等待一个停车位。有些车主没有耐心,给自己设定了一段等待时间,这段时间内等不到停车位就走了,如果等到了就开进去停车。而有些车主就像把车停在这,所以就一直等下去。

pthread_mutex 互斥锁

pthread_mutex 中也有个pthread_mutex_trylock(&pLock),和上面提到的 OSSpinLockTry(&oslock)区别在于,前者可以加锁时返回的是 0,否则返回一个错误提示码;后者返回的 YES和NO

pthread_mutex(recursive) 递归锁

经过上面几种例子,我们可以发现:加锁后只能有一个线程访问该对象,后面的线程需要排队,并且 lock 和 unlock 是对应出现的,同一线程多次 lock 是不允许的,而递归锁允许同一个线程在未释放其拥有的锁时反复对该锁进行加锁操作。

NSLock 普通锁

lock、unlock:不多做解释,和上面一样

trylock:能加锁返回 YES 并执行加锁操作,相当于 lock,反之返回 NO

lockBeforeDate:这个方法表示会在传入的时间内尝试加锁,若能加锁则执行加锁操作并返回 YES,反之返回 NO

NSCondition

wait:进入等待状态

waitUntilDate::让一个线程等待一定的时间

signal:唤醒一个等待的线程

broadcast:唤醒所有等待的线程

NSRecursiveLock 递归锁

上面已经大概介绍过了:

递归锁可以被同一线程多次请求,而不会引起死锁。这主要是用在循环或递归操作中。

@synchronized 条件锁

@synchronized 相信大家应该都熟悉,它的用法应该算这些锁中最简单的:

NSConditionLock 条件锁

NSConditionLock

相比于 NSLock 多了个 condition 参数,我们可以理解为一个条件标示

从上面的结果我们可以发现,NSConditionLock 还可以实现任务之间的依赖。

你可能感兴趣的:(iOS 开发中的八种锁(Lock))