1. os_unfair_lock 互斥鎖
- 需要導(dǎo)入
#import <os/lock.h> - 取代不安全的
SSpriLock,從iOS 10才開(kāi)始支持 - 底層等待的鎖的線程,不會(huì)盲等,線程會(huì)處于休眠狀態(tài)。
os_unfair_lock lock = OS_UNFAIR_LOCK_INIT;
os_unfair_lock_lock(&lock);
os_unfair_lock_unlock(&lock);
2.OSSpinLock 自旋鎖
- 需要引入頭文件
#import <libkern/OSAtomic.h>,并且在ios 10以后就不建議使用 - 它是個(gè)自旋鎖
- 自旋鎖只要有一個(gè)線程鎖住后,其他線程會(huì)盲等(循環(huán)等待)鎖,那個(gè)線程搶到那個(gè)線程就會(huì)執(zhí)行
- 會(huì)造成優(yōu)先級(jí)反轉(zhuǎn)問(wèn)題
- 如果等待鎖的優(yōu)先級(jí)比較高,它會(huì)一直占用CPU資源,優(yōu)先級(jí)低的線程無(wú)法釋放鎖
// 初始換一個(gè)lock
OSSpinLock lock = OS_SPINLOCK_INIT;
// 開(kāi)始鎖
OSSpinLockLock(&lock);
// 解鎖
OSSpinLockUnlock(&lock);
3.dispatch_semaphore 信號(hào)量
- 我們可以設(shè)置
dispatch_semaphore的value,來(lái)設(shè)置最大的并發(fā)數(shù),當(dāng)我們?cè)O(shè)置為1的時(shí)候,則可以代表鎖來(lái)使用
dispatch_semaphore_t semaphonre = dispatch_semaphore_create(1);
// wait 表示當(dāng)信號(hào)值 > 0的時(shí)候通過(guò),且信號(hào)值-1,
// 當(dāng)信號(hào)值 <= 0時(shí),表示等待,只到信號(hào)值 > 0 重復(fù)上一句
dispatch_semaphore_wait(semaphonre, DISPATCH_TIME_FOREVER);
// signal 表示信號(hào)值 +1
dispatch_semaphore_signal(semaphonre);
/**
DISPATCH_TIME_FOREVER: 表示永久等待
DISPATCH_TIME_NOW: 表示不等待
*/
4. pthread_mutex 互斥鎖
-
mutex為互斥鎖,等待鎖的線程會(huì)處于休眠狀態(tài)。 - 需要導(dǎo)入頭文件
#import <pthread.h> -
條件當(dāng)時(shí)用條件等待的時(shí)候會(huì)放開(kāi)當(dāng)前持有的鎖,等待signal或者broadcast后,再重新持有鎖,繼續(xù)執(zhí)行代碼 - 里面分為,默認(rèn)鎖和遞歸鎖。遞歸鎖需要設(shè)置
mutexattr的type為PTHREAD_MUTEX_RECURSIVE -
注意: 創(chuàng)建的
mutex、attr、cond等在不實(shí)用的時(shí)候,需要調(diào)用響應(yīng)的dispose方法進(jìn)行銷(xiāo)毀
// 初始化屬性
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr)
// 設(shè)置屬性
/*
PTHREAD_MUTEX_NORMAL 默認(rèn)
PTHREAD_MUTEX_RECURSIVE 遞歸鎖
PTHREAD_MUTEX_ERRORCHECK 錯(cuò)誤鎖
*/
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
// 初始化鎖
pthread_mutex_t mutex = {0};
// 第二個(gè)參數(shù)也可以填寫(xiě)為null,表示初始話一個(gè)默認(rèn)的??
pthread_mutex_init(&mutex,&attr);
// 銷(xiāo)毀類(lèi)型
pthread_mutexattr_destroy(&attr);
// 初始化條件
pthread_condattr_t condattr;
pthread_condattr_init(&condattr);
// 第二個(gè)參數(shù)也可以填寫(xiě)null,初始化一個(gè)默認(rèn)的添加
pthread_cond_init(&_cond, &condattr);
// 加??
pthread_mutex_lock(&_mutex);
// 解鎖
pthread_mutex_unlock(&_mutex);
// 條件等待
pthread_cond_wait(&_cond, &_mutex);
// 放開(kāi)其中一個(gè)鎖
pthread_cond_signal(&_cond);
// 發(fā)送一個(gè)廣播,放開(kāi)所有等待的鎖
pthread_cond_broadcast(&_cond);
5.NSLock
- 是對(duì)
pthread_mutex普通(默認(rèn))鎖的一個(gè)Objective-c的一個(gè)封裝。 - 是一個(gè)互斥鎖。
// 嘗試加鎖
- (BOOL)tryLock;
// 在這個(gè)時(shí)間之前加鎖,如果加鎖成功,則返回yes,不成功則為false
- (BOOL)lockBeforeDate:(NSDate *)limit;
- (void)lock;
- (void)unlock;
注意:NSLock在上一次lock之后并沒(méi)有unlok之前再次lock之后,會(huì)造成永遠(yuǎn)的死鎖。
6.NSCondition
- 是對(duì)
pthread_mutex默認(rèn)鎖 和 cond的封裝
- (void)wait;
- (BOOL)waitUntilDate:(NSDate *)limit;
- (void)signal;
- (void)broadcast;
7.NSConditionLock
-
NSConditionLock是對(duì)NSCondition的封裝,多出condition條件屬性,可以根據(jù)自己的邏輯來(lái)設(shè)置不同的條件condition - 一般可以設(shè)置線程之間的依賴(lài)
// 當(dāng)滿足condition的時(shí)候才加鎖
- (void)lockWhenCondition:(NSInteger)condition;
//嘗試獲取鎖對(duì)象,獲取成功需要配對(duì)unlock
- (BOOL)tryLock;
// 嘗試滿足condition加鎖
- (BOOL)tryLockWhenCondition:(NSInteger)condition; //同上
//解鎖,并且設(shè)置lock.condition = condition
- (void)unlockWithCondition:(NSInteger)condition;
8.NSRecursiveLock 遞歸鎖
- 是對(duì)
pthread_mutex遞歸鎖的一個(gè)Objective-C的封裝
// 嘗試加鎖
- (BOOL)tryLock;
// 在這個(gè)時(shí)間之前加鎖,如果加鎖成功,則返回yes,不成功則為false
- (BOOL)lockBeforeDate:(NSDate *)limit;
- (void)lock;
- (void)unlock;
9.@synchronized 遞歸鎖
-
synchronized是對(duì)當(dāng)前對(duì)象進(jìn)行加鎖,且底層使用的是pthread_mutex里面的Recursive模式加鎖 - 底層使用哈希表來(lái)儲(chǔ)存
lock和鎖對(duì)象之間的關(guān)聯(lián),使用的是鎖對(duì)象當(dāng)做key,lock當(dāng)作為值來(lái)儲(chǔ)存的哈西表里面。 - 每次進(jìn)來(lái)時(shí)會(huì)從哈希表取出
lock進(jìn)行??,結(jié)束的時(shí)候,會(huì)取出lock進(jìn)行unlock.
解釋?zhuān)?br> 遞歸鎖:表示同意線程可以多次重復(fù)加鎖,但是必須加鎖和解鎖為一一對(duì)應(yīng)。不同線程也是不可以多次加鎖
自旋鎖:表示等待加鎖的線程是一直循環(huán)等待,一直占用cpu資源
互斥鎖:表示等待加鎖的線程是處于休眠狀態(tài),等待鎖放開(kāi)后,喚起線程
自旋鎖、互斥鎖都是不可以在同一線程里面加鎖的,只有遞歸鎖是可以在同一線程加鎖