使用NSLock實(shí)現(xiàn)的鎖
? ? ? ?NSLock是Cocoa提供給我們最基本的鎖對(duì)象款熬,這也是我們經(jīng)常所使用的哪轿,除lock和unlock方法外坷襟,NSLock還提供了tryLock和lockBeforeDate:兩個(gè)方法撤嫩,前一個(gè)方法會(huì)嘗試加鎖,如果鎖不可用(已經(jīng)被鎖住)鹉梨,剛并不會(huì)阻塞線程讳癌,并返回NO。lockBeforeDate:方法會(huì)在所指定Date之前嘗試加鎖存皂,如果在指定時(shí)間之前都不能加鎖晌坤,則返回NO逢艘。
使用synchronized關(guān)鍵字構(gòu)建的鎖
? ? ? ?@synchronized指令使用的obj為該鎖的唯一標(biāo)識(shí),只有當(dāng)標(biāo)識(shí)相同時(shí)骤菠,才為滿足互斥它改,如果線程2中的@synchronized(obj)改為@synchronized(other),剛線程2就不會(huì)被阻塞,@synchronized指令實(shí)現(xiàn)鎖的優(yōu)點(diǎn)就是我們不需要在代碼中顯式的創(chuàng)建鎖對(duì)象商乎,便可以實(shí)現(xiàn)鎖的機(jī)制央拖,但作為一種預(yù)防措施,@synchronized塊會(huì)隱式的添加一個(gè)異常處理例程來(lái)保護(hù)代碼鹉戚,該處理例程會(huì)在異常拋出的時(shí)候自動(dòng)的釋放互斥鎖鲜戒。所以如果不想讓隱式的異常處理例程帶來(lái)額外的開銷,你可以考慮使用鎖對(duì)象抹凳。
使用GCD來(lái)實(shí)現(xiàn)的”鎖”
? ? ? ? 以上代碼構(gòu)建多線程我們就已經(jīng)用到了GCD的dispatch_async方法袍啡,其實(shí)在GCD中也已經(jīng)提供了一種信號(hào)機(jī)制,使用它我們也可以來(lái)構(gòu)建一把”鎖”(從本質(zhì)意義上講却桶,信號(hào)量與鎖是有區(qū)別境输,具體差異參加信號(hào)量與互斥鎖之間的區(qū)別):
NSRecursiveLock遞歸鎖
? ? ? ? NSRecursiveLock實(shí)際上定義的是一個(gè)遞歸鎖,這個(gè)鎖可以被同一線程多次請(qǐng)求颖系,而不會(huì)引起死鎖嗅剖。這主要是用在循環(huán)或遞歸操作中。我們先來(lái)看一個(gè)示例:
? ? ? ? 這段代碼是一個(gè)典型的死鎖情況嘁扼。在我們的線程中信粮,RecursiveMethod是遞歸調(diào)用的。所以每次進(jìn)入這個(gè)block時(shí)趁啸,都會(huì)去加一次鎖强缘,而從第二次開始,由于鎖已經(jīng)被使用了且沒(méi)有解鎖不傅,所以它需要等待鎖被解除旅掂,這樣就導(dǎo)致了死鎖,線程被阻塞住了访娶。調(diào)試器中會(huì)輸出如下信息:
value = 5
***?-[NSLock?lock]:?deadlock?('(null)')???***?Break?on?_NSLockError()?to?debug.
? ? ? ? 在這種情況下商虐,我們就可以使用NSRecursiveLock。它可以允許同一線程多次加鎖崖疤,而不會(huì)造成死鎖秘车。遞歸鎖會(huì)跟蹤它被lock的次數(shù)。每次成功的lock都必須平衡調(diào)用unlock操作劫哼。只有所有達(dá)到這種平衡叮趴,鎖最后才能被釋放,以供其它線程使用
NSConditionLock條件鎖
? ? ? ? 當(dāng)我們?cè)谑褂枚嗑€程的時(shí)候权烧,有時(shí)一把只會(huì)lock和unlock的鎖未必就能完全滿足我們的使用眯亦。因?yàn)槠胀ǖ逆i只能關(guān)心鎖與不鎖咳蔚,而不在乎用什么鑰匙才能開鎖,而我們?cè)谔幚碣Y源共享的時(shí)候搔驼,多數(shù)情況是只有滿足一定條件的情況下才能打開這把鎖:
? ? ? ?在線程1中的加鎖使用了lock谈火,所以是不需要條件的,所以順利的就鎖住了舌涨,但在unlock的使用了一個(gè)整型的條件糯耍,它可以開啟其它線程中正在等待這把鑰匙的臨界地,而線程2則需要一把被標(biāo)識(shí)為2的鑰匙囊嘉,所以當(dāng)線程1循環(huán)到最后一次的時(shí)候温技,才最終打開了線程2中的阻塞。但即便如此扭粱,NSConditionLock也跟其它的鎖一樣舵鳞,是需要lock與unlock對(duì)應(yīng)的,只是lock,lockWhenCondition:與unlock琢蛤,unlockWithCondition:是可以隨意組合的蜓堕,當(dāng)然這是與你的需求相關(guān)的。
NSDistributedLock分布式鎖
? ? ? ? 以上所有的鎖都是在解決多線程之間的沖突博其,但如果遇上多個(gè)進(jìn)程或多個(gè)程序之間需要構(gòu)建互斥的情景該怎么辦呢套才?這個(gè)時(shí)候我們就需要使用到NSDistributedLock了,從它的類名就知道這是一個(gè)分布式的Lock慕淡,NSDistributedLock的實(shí)現(xiàn)是通過(guò)文件系統(tǒng)的背伴,所以使用它才可以有效的實(shí)現(xiàn)不同進(jìn)程之間的互斥,但NSDistributedLock并非繼承于NSLock峰髓,它沒(méi)有l(wèi)ock方法傻寂,它只實(shí)現(xiàn)了tryLock,unlock携兵,breakLock疾掰,所以如果需要lock的話,你就必須自己實(shí)現(xiàn)一個(gè)tryLock的輪詢眉孩,下面通過(guò)代碼簡(jiǎn)單的演示一下吧:
? ? ? 先運(yùn)行程序A,然后立即運(yùn)行程序B,根據(jù)打印你可以清楚的發(fā)現(xiàn)个绍,當(dāng)程序A剛運(yùn)行的時(shí)候勒葱,程序B一直處于等待中浪汪,當(dāng)大概10秒過(guò)后,程序B便打印出了appB:OK的輸出凛虽,以上便實(shí)現(xiàn)了兩上不同程序之間的互斥死遭。/Users/mac/Desktop/earning__是一個(gè)文件或文件夾的地址,如果該文件或文件夾不存在凯旋,那么在tryLock返回YES時(shí)呀潭,會(huì)自動(dòng)創(chuàng)建該文件/文件夾钉迷。在結(jié)束的時(shí)候該文件/文件夾會(huì)被清除,所以在選擇的該路徑的時(shí)候钠署,應(yīng)該選擇一個(gè)不存在的路徑糠聪,以防止誤刪了文件。
? ? ? ? 這是用在多進(jìn)程之間共享資源的鎖谐鼎,對(duì) iOS 來(lái)說(shuō)暫時(shí)沒(méi)用處舰蟆。
參考文獻(xiàn)
1.www.tanhao.me/pieces/616.html/
3.www.tanhao.me/pieces/643.html/
4.www.tanhao.me/pieces/1731.html/
5.iOS 鎖