美文网首页
iOS中的锁 笔记

iOS中的锁 笔记

作者: 我才是臭吉吉 | 来源:发表于2019-08-02 11:14 被阅读0次

    <u>会阻塞线程的锁,都属于互斥锁</u>

    NSLock

    NSLock的lock方法和lockBeforeDate: 方法会阻塞线程;tryLock方法不会阻塞线程。
    多个线程同时加锁时,其他请求锁的线程按照先进先出执行。

    NSConditionLock

    NSConditionLock与NSLock行为相似,只不过可以设置条件(condition整数),可以设置为在满足condition时才进行lockWithCondition:unlockWithCondition:tryLockWithCondition: 等操作(当然也可以不设置条件)。

    可以使用NSConditionLock设置线程(任务)间的依赖关系,用GCD可以结合着使用进行实现

    NSRecursiveLock

    递归锁。可以在单个线程中返回加锁或解锁,其自身会记录加锁和解锁的次数,只有次数匹配时,才会真正的解锁,其他线程才可以加锁成功。

    NSLock、NSConditionLock和NSRecursiveLock是先轮询,之后再进入waiting状态。

    NSCondition

    NSCondition由 一个锁 + 条件检查器 组成。在每个线程中,都可以对condition对象单独进行lockunlock,不影响其他线程再次加锁或解锁。

    condition对象调用wait后,直接进入waiting状态,阻塞当前线程执行。等待其他线程对condition调用signalbroadcast 后,唤醒1个或所有的waiting线程,继续向下执行。

    以上四种锁都是遵循NSLocking协议。

    @synchronized

    @synchronized同步锁会将指定的参数对象进行加锁。只有对相同对象进行加锁时,后加锁的线程才会被阻塞。否则无效。

    dispatch_semaphore

    信号量是GCD进行同步的一种方式。
    通过dispatch_semaphore_create创建信号量(指定信号值,即同时执行的任务数)。dispatch_semaphore_wait函数会对信号值进行检测:当信号值大于1时,信号值减1,继续向下执行任务,在信号值是1的信号量中,相当于加锁操作;当信号值为0时,调用线程被阻塞。只有当其他线程调用dispatch_semaphpre_signal进行信号恢复后(保证信号值重新大于0),被阻塞的线程继续向下执行。

    **dispatch_semaphore与NSCondition都是基于信号的锁,区别是信号量会保存发送的信号,NSCondition则不可以(只能signal)。

    OSSpinLock

    自旋锁现在已经不建议使用了,具体原因见上面(优先级反转造成死锁)。
    苹果推荐使用<os/lock.h>中的os_unfair_lock() 锁替代。

    自旋锁与互斥锁都是抢占式,任何时候都只能有一个保持者。区别是:互斥锁中,调用者在别的运算单元抢占锁后进入睡眠,等待结束后被唤醒进行抢占;自旋锁,调用者在被运算单元抢占锁后不睡眠,循环查看自旋锁是否被释放。
    故自旋锁适合保持锁时间较短的情况,这种情况下其效率远高于互斥锁。

    缺点:需要获取锁的线程优先级相同。如果低优先级的线程获得锁后,高优先级线程会处于busy-wait状态,占用大量CPU。而低优先级线程无法获取CPU时间,导致任务无法完成,也就无法释放锁。造成死锁(优先级反转)。

    参考资料:

    相关文章

      网友评论

          本文标题:iOS中的锁 笔记

          本文链接:https://www.haomeiwen.com/subject/whokdctx.html