鎖的意義就是為了防止在多線程(多任務(wù))的情況下對(duì)共享資源(臨界資源)的臟讀或者臟寫辆影。也可以理解為:用于執(zhí)行多線程操作時(shí)強(qiáng)行限制資源訪問(wèn)的同步機(jī)制徒像,即并發(fā)控制中保證互斥的要求,可以理解成它用于排除并發(fā)的一種策略蛙讥。
分類方式 | 分類 |
---|---|
按鎖的粒度劃分 | 表級(jí)鎖锯蛀、行級(jí)鎖、頁(yè)級(jí)鎖 |
按鎖的級(jí)別劃分 | 共享鎖键菱、排他鎖 |
按加鎖方式劃分 | 自動(dòng)鎖谬墙、顯示鎖 |
按鎖的使用方式劃分 | 樂(lè)觀鎖、悲觀鎖 |
按操作劃分 | DML鎖经备、DDL鎖 |
等等拭抬。。 | 等等侵蒙。造虎。 |
方式1 使用NSLock類
- 該類分成了幾個(gè)子類:NSLock、NSConditionLock(條件鎖)纷闺、NSRecursiveLock(遞歸鎖)以及NSCondition算凿。
- 類內(nèi)方法:
tryLock
:作用是嘗試獲取一個(gè)鎖,并且立刻返回Bool值犁功,YES表示獲取了鎖氓轰,NO表示沒(méi)有獲取鎖失敗。
lockBeforeDate:
:作用是在某個(gè)時(shí)刻之前獲取鎖浸卦,如果獲取成功署鸡,則返回YES,NO表示獲取鎖失敗限嫌。
- (void)lockDemo1 {
NSLock *myLock = [[NSLock alloc] init];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[myLock lock];
NSLog(@"執(zhí)行鎖1");
sleep(5);
[myLock unlock];
if ([myLock tryLock]) {
NSLog(@"可以獲得鎖1");
}else {
NSLog(@"不可以獲得鎖1");
}
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(1);
if ([myLock tryLock]) {
NSLog(@"---可以獲得鎖2");
}else {
NSLog(@"----不可以獲得所2");
}
[myLock lock];
NSLog(@"執(zhí)行鎖2");
[myLock unlock];
});
}
方式2 使用@synchorize
- 對(duì)于@synchorize指令中使用的testLock為該鎖標(biāo)示靴庆,只有標(biāo)示相同的時(shí)候才滿足鎖的效果。它的優(yōu)點(diǎn)是不用顯式地創(chuàng)建鎖怒医,便可以實(shí)現(xiàn)鎖的機(jī)制炉抒。但是它會(huì)隱式地添加異常處理程序來(lái)保護(hù)代碼,該程序在拋出異常的時(shí)候自動(dòng)釋放鎖稚叹。
- (void)lockDemo2 {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized (self) {
NSLog(@"執(zhí)行鎖1");
sleep(5);
}
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(1);
@synchronized (self) {
NSLog(@"執(zhí)行鎖2");
}
});
}
方式3 使用gcd
- (void)lockDemo3 {
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"執(zhí)行鎖1");
sleep(5);
dispatch_semaphore_signal(semaphore);
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(1);
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"執(zhí)行鎖2");
dispatch_semaphore_signal(semaphore);
});
}
方式4 使用phtread
- (void)lockDemo4 {
__block pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
//線程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
pthread_mutex_lock(&mutex);
NSLog(@"執(zhí)行鎖1");
sleep(5);
pthread_mutex_unlock(&mutex);
});
//線程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(1);
pthread_mutex_lock(&mutex);
NSLog(@"執(zhí)行鎖2");
pthread_mutex_unlock(&mutex);
});
}
方式5 OSSpinLock
- (void)lockDemo4 {
OSSpinLock spinlock = OS_SPINLOCK_INIT;
//線程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
OSSpinLockLock(&spinlock);
NSLog(@"執(zhí)行鎖1");
sleep(5);
OSSpinLockUnlock(&spinlock);
});
//線程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(1);
OSSpinLockLock(&spinlock);
NSLog(@"執(zhí)行鎖2");
OSSpinLockUnlock(&spinlock);
});
}
同樣加鎖解鎖次數(shù)耗時(shí)結(jié)果比較:
OSSpinlock
< pthread_mutex
< NSLock+IMP
< NSLock
< @synchronized
- 1焰薄、@synchronized
內(nèi)部會(huì)創(chuàng)建一個(gè)異常捕獲的handler和其他內(nèi)部使用的鎖。由于內(nèi)部會(huì)添加異常處理扒袖,所以耗時(shí)塞茅。- 2、NSLock 和 NSLock+IMP
兩個(gè)時(shí)間非常接近僚稿。他們是pthread mutexes
封裝的,但是創(chuàng)建對(duì)象的時(shí)候需要額外的開銷蟀伸。- 3蚀同、pthread_mutex
底層的API缅刽,性能比較高,處理能力不錯(cuò)蠢络。- 4衰猛、gcd
系統(tǒng)封裝的C代碼效果比pthread好。- 5刹孔、OSSpinLock
自旋鎖不進(jìn)入內(nèi)核啡省,僅僅是重新加載。如果自旋鎖占用的時(shí)間是極少的(通常是納秒級(jí)別的)性能還是比較高的髓霞,減少了系統(tǒng)的直接調(diào)用和上下文的切換卦睹。(因?yàn)閮?yōu)先級(jí)倒置問(wèn)題已經(jīng)棄用,此類已經(jīng)被os_unfair_lock所替)
耗時(shí)結(jié)果如下: synthorize > NSLock > pthread > gcd > os_unfair_lock >OSSPinLock