一般而言,锁的功能越强大,性能就会越低。
锁的作用:避免多个线程在某一时刻同时操作一个共享资源。
自旋锁:busy-waiting
OSSpinLock ,os_unfair_lock ,NSSpinLock(对象锁)
当线程没有获取到锁时,会一直循环查看锁是否可用。线程一直处于活跃状态,不会进入休眠。自旋锁让CPU一直不断循环请求获取这个锁,期间CPU不做其他事,直到获取这个锁为止。
优点:一旦锁释放,立刻就能执行,不需要唤醒,执行效率较高。避免了进程上下文的调度开销
缺点:自旋锁 比较耗费CPU资源,因为优先级反转的问题被废弃使用了
使用场景:保护执行时间非常短的临界区。
注意: 进入临界区后不能调用可能引起系统休眠的函数。不能被中断函数重入调用。不然会引起死锁。
互斥锁:sleep-waiting
只有一个线程可以获取互斥锁,线程在释放互斥锁之前其他线程都不能获取该互斥锁。如果其他线程想要获取这个互斥锁,那么这个线程只能以阻塞方式进行等待,进入休眠状态。等到锁被释放,线程会被唤醒同时获取到锁。继续执行任务改变线程状态。
优点:当前线程发生阻塞时,可以让CPU去处理其他的任务。
缺点:需要修改线程状态,唤醒或休眠线程,效率较低。
使用场景:适用于时间长相对自旋锁效率低的场景。
互斥锁又分 递归锁(NSRecursiveLock 等) 和 非递归锁(NSLock 等)。
递归锁:可重入锁,线程在锁释放前可再次获取锁,可以递归调用,多次执行 lock 操作。
非递归锁:不可重入,必须等锁释放后才能再次获取锁,不能多次lock ,一个lock 对应一个解锁操作。
C语言互斥锁:pthread_mutex , pthread_mutex(recursive) (递归锁), @synchronized (obj)(条件锁)
GCD :dispatch_semaphore (信号量)
对象互斥锁:NSLock ,NSCondition (条件锁),NSConditionLock (条件锁),
1. NSLock :遵循 NSLocking 协议。不能多次调用 lock方法,会造成死锁, NSLock 是对 pthread_mutex互斥锁 的封装。
-lock和-unlock 必须在同一个线程中成对调用。
timedLock( ) 的实现流程:
1. 设定超时时间,进入while循环。
2. pthread_cond_timedwait() 在本次循环中计时等待,线程进入休眠
3. 等待超时,直接返回 false;
4. 如果等待没有超时,期间锁被释放,线程会被唤醒,再次尝试获取锁 pthread_mutex_trylock(),如果获取成功返回true
5. 没有超时,被唤醒后也没有成功获取到锁(被其他线程抢先获得锁),重新计算超时时间进入下一次while循环
2. @synchronized(obj) : 使用的 obj 对象为该锁的唯一标识,只有当标识相同时,才为满足互斥条件,不然锁不住。 用着更方便,可读性更高。
3. 读写锁:pthread_rwlock : 多个读操作可并发执行,写操作时互斥的,只能执行一个写操作。通常用互斥锁、条件变量、信号量实现。
4. NSDistributedLock分布式锁:是通过文件系统实现的,使可以有效的实现不同进程之间的互斥。 NSDistributedLock 并非继承于NSLock,它没有lock方法,只实现了tryLock,unlock,breakLock,需要lock的话,必须自己实现一个tryLock的轮询。
5. NSConditionLock: 条件锁,某些资源要求不满足条件时就锁住进入休眠。当资源被分配到了条件满足时,条件锁打开继续运行。条件锁调用wait 方法就把当前线程进入等待状态,当调用了signal 方法 或者 broadcast广播方法 就可以让该线程继续执行。

5.2 NSCondition: 是互斥锁和条件锁的结合体,充当线程中的锁和检查器, 锁用来检测条件--保护数据源, 线程检查器根据条件决定是否继续运行线程,即线程是否被阻塞。条件不成立时,线程会阻塞,在另一个线程向条件对象发出信号之前,它一直保持阻塞状态。

6. GCD :dispatch_semaphore (信号量):更高级的同步机制,有更多的取值空间。可实现更加复杂的同步,而不单单是线程间互斥。
semphone在一定程度也可以当互斥锁用,它适用于编程逻辑更复杂的场景,同时它也是除了自旋锁以外性能最高的锁。
7. NSRecursiveLock (递归锁) :递归锁可以被同一线程多次请求,而不会引起死锁。允许同一个线程在未释放其拥有的锁时反复对该锁进行加锁操作。, 执行锁中的代码。主要是用在循环或递归操作中。
递归锁使用: 图片失败重传功能、上传多张图片
参考:
c++线程中的几种锁_bian_qing_quan11的博客-CSDN博客_c++锁 条件锁 & 自旋锁 写的很详细 c++ 层面上的解析
IOS中实现线程加锁的几个方法_zhenxi_20的专栏-CSDN博客 NSConditionLock条件锁 &NSRecursiveLock 解析 & NSRecursiveLock递归锁 oc 对象的🔐
iOS线程锁及其性能 - 简书 各种锁的简单使用介绍
再解析下内核自旋锁和优先级翻转问题_嵌入式Linux-CSDN博客 自旋锁的使用注意点 2点
网友评论