ios中常用的鎖
為什么要用到鎖?鎖是什么
在平時(shí)的開(kāi)發(fā)過(guò)程中,為了提升我們應(yīng)用程序的運(yùn)行效率趴泌,性能,我們會(huì)經(jīng)常使用到多線程拉庶,在使用多線程的過(guò)程中嗜憔,我們可能會(huì)遇到不同線程搶奪資源的問(wèn)題,這個(gè)就涉及到一個(gè)線程安全的問(wèn)題氏仗。
什么是線程安全
那么是線程安全呢吉捶?其實(shí)非常好理解,當(dāng)一個(gè)線程訪問(wèn)一個(gè)數(shù)據(jù)的時(shí)候皆尔,其他的線程不能對(duì)他訪問(wèn)呐舔,知道線程訪問(wèn)結(jié)束為止。如果同一時(shí)刻慷蠕,允許其他進(jìn)程訪問(wèn)一個(gè)數(shù)據(jù)的時(shí)候珊拼,我們稱(chēng)之為線程不安全
鎖誕生了
為了線程安全,能保證同一時(shí)刻只有同一個(gè)線程來(lái)對(duì)同一個(gè)數(shù)據(jù)源進(jìn)行訪問(wèn)流炕,這就是鎖
ios日常開(kāi)發(fā)中最常見(jiàn)的鎖
@synchronized
互斥鎖澎现,平時(shí)經(jīng)常看到的一中寫(xiě)法每辟,這個(gè)鎖的性能其實(shí)是比較差的剑辫,但是代碼量比較少,使用簡(jiǎn)單渠欺。
@synchronized () { }
dispatch_queue_t que = dispatch_queue_create("測(cè)試隊(duì)列1",DISPATCH_QUEUE_CONCURRENT);
dispatch_async(que, ^{
@synchronized (self) {
sleep(2);
NSLog(@"任務(wù)1");
}
});
dispatch_async(que, ^{
@synchronized (self) {
NSLog(@"任務(wù)2");
}
});
NSLock
互斥鎖妹蔽。蘋(píng)果提供的最簡(jiǎn)單的鎖。使用方式也非常簡(jiǎn)單挠将。但是連續(xù)鎖了兩次會(huì)造成死鎖胳岂。
性能是優(yōu)于@synchronized
NSLock *lock = [[NSLock alloc]init];
dispatch_async(que, ^{
[lock lock];
sleep(3);
NSLog(@"任務(wù)1");
[lock unlock];
});
dispatch_async(que, ^{
[lock lock];
NSLog(@"任務(wù)2");
[lock unlock];
});
如果我們需要在遞歸的時(shí)候重復(fù)調(diào)用鎖怎么辦這個(gè)時(shí)候我們可以用NSRecursiveLock
NSRecursiveLock
遞歸鎖,可以在同一線程多次lock
NSLock *lock = [[NSLock alloc]init];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
static void(^testMethod)(int);
testMethod = ^(int value){
[lock lock];
[NSThread sleepForTimeInterval:1];
NSLog(@"%@",[NSThread currentThread]);
if (value > 0) {
NSLog(@"----%d", value);
testMethod(value - 1);
}
[lock unlock];
};
testMethod(4);
});
這段代碼第一次進(jìn)來(lái)的時(shí)候沒(méi)有unlock 當(dāng)?shù)诙芜M(jìn)來(lái)的時(shí)候舔稀,則會(huì)造成死鎖旦万。非常常見(jiàn),但經(jīng)常被忽略的錯(cuò)誤镶蹋。這個(gè)時(shí)候我們就要用NSRecursiveLock
NSRecursiveLock *lock = [[NSRecursiveLock alloc]init];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
static void(^testMethod)(int);
testMethod = ^(int value){
[lock lock];
[NSThread sleepForTimeInterval:1];
NSLog(@"%@",[NSThread currentThread]);
if (value > 0) {
NSLog(@"----%d", value);
testMethod(value - 1);
}
[lock unlock];
};
testMethod(4);
});
NSConditionLock
條件鎖成艘,也是繼承NSLocking協(xié)議赏半,比nslock多了個(gè)條件參數(shù)condition
NSConditionLock *lock = [[NSConditionLock alloc]initWithCondition:0];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[lock lockWhenCondition:0];
sleep(2);
NSLog(@"任務(wù)1");
[lock unlockWithCondition:3];
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[lock lockWhenCondition:15];
sleep(2);
NSLog(@"任務(wù)2");
[lock unlockWithCondition:16];
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[lock lockWhenCondition:3];
sleep(5);
NSLog(@"任務(wù)3");
[lock unlockWithCondition:15];
});
總結(jié)
掌握前面幾個(gè)簡(jiǎn)單的鎖,基本可以對(duì)付日常的開(kāi)發(fā)需求咯淆两。當(dāng)然還有其他OSSpinLock
断箫,dispatch_semaphore
等等,建議還是用蘋(píng)果爸爸的api秋冰,簡(jiǎn)單仲义,好用,性能也不算太差剑勾。有什么意見(jiàn)錯(cuò)誤埃撵,歡迎指正。