OSSpinLock
OSSpinLock 自旋鎖,不會(huì)讓等待的線程進(jìn)入睡眠狀態(tài),效率高。
OSSpinLock 不能保證安全。系統(tǒng)維護(hù)了5個(gè)不同的線程優(yōu)先級(jí)/QoS: background蛙讥,utility,default灭衷,user-initiated次慢,user-interactive。高優(yōu)先級(jí)線程始終會(huì)在低優(yōu)先級(jí)線程前執(zhí)行翔曲,一個(gè)線程不會(huì)受到比它更低優(yōu)先級(jí)線程的干擾迫像。這種線程調(diào)度算法會(huì)差生潛在的優(yōu)先級(jí)反轉(zhuǎn)問(wèn)題,從而破壞spin Lock
優(yōu)先級(jí)反轉(zhuǎn):如果一個(gè)低優(yōu)先級(jí)的線程獲得鎖并訪問(wèn)共享資源瞳遍,這時(shí)一個(gè)高優(yōu)先級(jí)的線程也嘗試獲得該鎖闻妓,它會(huì)處于spin lock 的忙等狀態(tài)從而占用大量CPU。此時(shí)低優(yōu)先級(jí)線程無(wú)法與高優(yōu)先級(jí)線程爭(zhēng)奪CPU時(shí)間掠械,從而導(dǎo)致任務(wù)遲遲完不成由缆、無(wú)法釋放Lock。
最終的結(jié)論就是猾蒂,除非開發(fā)者能保證訪問(wèn)鎖的線程全部都處于同一優(yōu)先級(jí)均唉,否則 iOS 系統(tǒng)中所有類型的自旋鎖都不能再使用了
OS_SPINLOCK_INIT:默認(rèn)值為0,在locked狀態(tài)時(shí)婚夫,就會(huì)大于0浸卦,unlocked 狀態(tài)下為 0
OSSpinLockLock(&oslock):上鎖,參數(shù)為OSSpinLock 地址
OSSpinLockUnlock(&oslock):解鎖案糙,參數(shù)為OSSpinLock 地址
OSSpinLockTry(&oslock):嘗試加鎖,可以加鎖則立即加鎖靴庆,并返回YES时捌,反之返回NO。
dispatch_semaphore 信號(hào)量
dispatch_semaphore_create(1) 傳值必須 >=0 ,若傳為0炉抒,則阻塞線程并等待
dispatch_semaphore_wait(signal, overTime): 可以理解為lock奢讨,會(huì)使得signal值 -1
dispatch_semaphore_signal(signal): 可以理解為unlock, 會(huì)使得signal值 +1
phread_mutex
static pthread_mutex_t pLock;
pthread_mutex_init(&pLock, NULL);
pthread_mutex_lock(&pLock);
pthread_mutex_unlock(&pLock);
#pthread_mutex 中也有個(gè)pthread_mutex_trylock(&pLock), 和上面提到的OSSpinLockTry(&oslock)區(qū)別在于,前者可以加鎖時(shí)返回的是0焰薄,否則返回一個(gè)錯(cuò)誤提示碼拿诸;后者返回的YES 和 NO
pthread_mutex(recursive)遞歸鎖
加鎖后只能有一個(gè)線程訪問(wèn)該對(duì)象扒袖,后面的線程需要排隊(duì),并且 lock 和 unlock 是對(duì)應(yīng)出現(xiàn)的亩码,同一線程多次 lock 是不允許的季率,而遞歸鎖允許同一個(gè)線程在未釋放其擁有的鎖時(shí)反復(fù)對(duì)該鎖進(jìn)行加鎖操作
static pthread_mutex_t pLock;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr); //初始化attr并且給它賦予默認(rèn)
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); //設(shè)置鎖類型,這邊是設(shè)置為遞歸鎖
pthread_mutex_init(&pLock, &attr);
pthread_mutexattr_destroy(&attr); //銷毀一個(gè)屬性對(duì)象描沟,在重新進(jìn)行初始化之前該結(jié)構(gòu)不能重新使用
pthread_mutex_lock(&pLock);
pthread_mutex_unlock(&pLock);
NSLock
lock 飒泻、unlock 、tryLock 能加鎖返回YES并執(zhí)行加鎖操作吏廉,相當(dāng)于lock泞遗,反之返回NO
NSLock *lock = [NSLock new];
[lock lock]
[lock unlock]
NSCondition
wait:進(jìn)入等待狀態(tài)
waitUntilDate:讓一個(gè)線程等待一定的時(shí)間
signal: 喚醒一個(gè)等待的線程
broadcast: 喚醒所有等待的線程
// 等待2秒
NSCondition *cLock = [NSCondition new];
//線程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"start");
[cLock lock];
[cLock waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:2]];
NSLog(@"線程1");
[cLock unlock];
});
// 喚醒一個(gè)等待線程
NSCondition *cLock = [NSCondition new];
//線程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[cLock lock];
NSLog(@"線程1加鎖成功");
[cLock wait];
NSLog(@"線程1");
[cLock unlock];
});
//線程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[cLock lock];
NSLog(@"線程2加鎖成功");
[cLock wait];
NSLog(@"線程2");
[cLock unlock];
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(2);
NSLog(@"喚醒一個(gè)等待的線程");
[cLock signal];
});
// 喚醒所有等待的線程
.........
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(2);
NSLog(@"喚醒所有等待的線程");
[cLock broadcast];
});
NSRecursiveLock 遞歸鎖
NSRecursiveLock *rLock = [NSRecursiveLock new];
[rLock lock];
[rLock unlock];
@synchronized
//線程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized (self) {
sleep(2);
NSLog(@"線程1");
}
});
//線程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized (self) {
NSLog(@"線程2");
}
});
NSConditionLock 條件鎖
NSConditionLock *cLock = [[NSConditionLock alloc] initWithCondition:0];
//線程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if([cLock tryLockWhenCondition:0]){
NSLog(@"線程1");
[cLock unlockWithCondition:1];
}else{
NSLog(@"失敗");
}
});
//線程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[cLock lockWhenCondition:3];
NSLog(@"線程2");
[cLock unlockWithCondition:2];
});
//線程3
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[cLock lockWhenCondition:1];
NSLog(@"線程3");
[cLock unlockWithCondition:3];
});
參考:
ios 中會(huì)使用到的鎖