线程锁

作者: 六横六竖亚 | 来源:发表于2020-07-09 16:08 被阅读0次

    多线程下为了访问安全,对同一块资源按照顺序进行的线程同步技术,加锁最常见。

    OSSpinLock 自旋锁

    申请锁的操作为原子操作,保证只有一个线程在申请锁。

    原理:执行do-while循环,忙等,不切线程,适合小的等待操作,效率最高。

    缺点:1、递归调用可能死锁;2、其他线程未获得锁的情况下一直自旋占用CPU;3、多线程下的优先级反转问题(低优先级线程先获得锁,高优先级线程循环忙等申请锁占用大量CPU,低优先级线程无法争抢到资源导致无法完成任务释放锁)

    注:iOS10下推出os_unfair_lock_t来代替,线程会进入休眠而非忙等。

    pthread_mutex 互斥锁

    原理和信号量类似,遇锁时让出时间片进入休眠,等待上下文切换唤醒,由于系统切换上下文需要时间,所以比较适合等待时间较长的场景(如果等待时间较短,忙等比休眠更高效且不消耗CPU资源)。总体性能仅次于自旋锁和信号量。

    NORMAL普通锁:等待队列,先进先出获得锁。

    ERRORCHECK检错锁(NSLock):同一个线程请求锁会返回错误防止嵌套死锁,其他线程访问同普通锁。

    RECURSIVE递归锁(NSRecursiveLock):允许同一线程多次获得锁和多次unlock解锁,要一一对应。

    DEFAULT适应锁:锁释放后重新竞争,没有等待队列。

    互斥锁和自旋锁的比较

    自旋锁会产生优先级反转,用互斥锁会比较安全。

    自旋锁在循环等待的时候会消耗cpu的性能。

    互斥锁在cpu线程调度的时候会消耗cpu性能。

    所以:互斥锁,比较适合临界代码比较耗时间的,如有网络阻塞、IO阻塞的情况。自旋锁, 因为一直消耗cpu,所以一般比较适合临界代码比较少的,比较适合短时间操作的,如从mutable对象里面(dictioanry array hashtable) 读写操作的情况。

    dispatch_semaphore 信号量加锁

    GCD的一种同步方式,采用信号量的实现原理加锁,性能第二。

    signal = dispatch_semaphore_create(long value > 0)  //创建信号量

    dispatch_semaphore_signal(signal)  //传入的信号量+1

    dispatch_semaphore_wait(signal, timeout)  //信号量>0则执行代码,并信号量-1;若=0则进入wait;wait过程中执行了dispatch_semaphore_signal,则继续执行;如果wait直到timeOut,也会继续执行。

    注:互斥锁和信号量的区别?互斥锁主要对资源加锁,信号量更偏向于流程的概念,可以跨线程。

    @synchronize 同步锁

    @synchronize(self) { //lock,do Something }

    传入对象作为标记,Runtime为对象创建一个递归锁存在hash表中。牺牲性能,提供可读性和用法便利。

    atomic原子操作

    底层实现:get方法(objc_getProperty)、set方法(reallySetProperty)内,用了spinlock_t(其实底层用了mutex_t互斥锁替换以前的自旋锁)锁进行加锁解锁操作。

    注:atomic一定线程安全吗?否。因为只锁了get、set方法,只保证进入时安全,不保证多线程访问下的资源安全。

    相关问题

    自旋锁和互斥锁的区别,分别有什么优缺点

    (OSSpinLock是执行循环忙等不切线程,适合小的等待操作,效率高;互斥锁是让出时间片进入休眠等待切换上下文唤醒,适合等待时间长的场景自旋锁多线程优先级反转问题,会导致高优先级线程忙等占用大量CPU,所以用unfair替换了)

    互斥锁有哪些类型

    (普通锁:先进先出的等待队列;检错锁:同一线程请求锁会返回错误;递归锁:允许同一线程多次对应的加解锁;适应锁:释放后重新竞争,没有等待队列)

    互斥锁和信号量的区别

    (互斥锁主要对资源加锁,信号量更偏向于流程的概念,可以跨线程。)

    atomic一定线程安全吗

    (否。因为原子操作只锁了属性的get和set方法(用了os_unfair_lock)。)

    优先级反转问题

    (自旋锁由于忙等,低优先级任务加锁后,被高优先级任务抢占时间片,导致锁无法释放的问题解决:优先级继承(继承最高的优先级),优先级天花板(进入临界区都设置为最高优先级),禁止中断。用其他锁代替:pthread_mutex互斥锁或semaphore信号量,由于是切时间片所以不会产生优先级反转)

    相关文章

      网友评论

          本文标题:线程锁

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