<u>會阻塞線程的鎖,都屬于互斥鎖</u>
NSLock
NSLock的lock方法和lockBeforeDate: 方法會阻塞線程;tryLock方法不會阻塞線程。
多個線程同時加鎖時,其他請求鎖的線程按照先進(jìn)先出執(zhí)行。
NSConditionLock
NSConditionLock與NSLock行為相似,只不過可以設(shè)置條件(condition整數(shù)),可以設(shè)置為在滿足condition時才進(jìn)行lockWithCondition:、unlockWithCondition:、tryLockWithCondition: 等操作(當(dāng)然也可以不設(shè)置條件)。
故可以使用NSConditionLock設(shè)置線程(任務(wù))間的依賴關(guān)系,用GCD可以結(jié)合著使用進(jìn)行實現(xiàn)。
NSRecursiveLock
遞歸鎖。可以在單個線程中返回加鎖或解鎖,其自身會記錄加鎖和解鎖的次數(shù),只有次數(shù)匹配時,才會真正的解鎖,其他線程才可以加鎖成功。
NSLock、NSConditionLock和NSRecursiveLock是先輪詢,之后再進(jìn)入waiting狀態(tài)。
NSCondition
NSCondition由 一個鎖 + 條件檢查器 組成。在每個線程中,都可以對condition對象單獨進(jìn)行lock和unlock,不影響其他線程再次加鎖或解鎖。
condition對象調(diào)用wait后,直接進(jìn)入waiting狀態(tài),阻塞當(dāng)前線程執(zhí)行。等待其他線程對condition調(diào)用signal 或 broadcast 后,喚醒1個或所有的waiting線程,繼續(xù)向下執(zhí)行。
以上四種鎖都是遵循NSLocking協(xié)議。
@synchronized
@synchronized同步鎖會將指定的參數(shù)對象進(jìn)行加鎖。只有對相同對象進(jìn)行加鎖時,后加鎖的線程才會被阻塞。否則無效。
dispatch_semaphore
信號量是GCD進(jìn)行同步的一種方式。
通過dispatch_semaphore_create創(chuàng)建信號量(指定信號值,即同時執(zhí)行的任務(wù)數(shù))。dispatch_semaphore_wait函數(shù)會對信號值進(jìn)行檢測:當(dāng)信號值大于1時,信號值減1,繼續(xù)向下執(zhí)行任務(wù),在信號值是1的信號量中,相當(dāng)于加鎖操作;當(dāng)信號值為0時,調(diào)用線程被阻塞。只有當(dāng)其他線程調(diào)用dispatch_semaphpre_signal進(jìn)行信號恢復(fù)后(保證信號值重新大于0),被阻塞的線程繼續(xù)向下執(zhí)行。
**dispatch_semaphore與NSCondition都是基于信號的鎖,區(qū)別是信號量會保存發(fā)送的信號,NSCondition則不可以(只能signal)。
OSSpinLock
自旋鎖現(xiàn)在已經(jīng)不建議使用了,具體原因見上面(優(yōu)先級反轉(zhuǎn)造成死鎖)。
蘋果推薦使用<os/lock.h>中的os_unfair_lock() 鎖替代。
自旋鎖與互斥鎖都是搶占式,任何時候都只能有一個保持者。區(qū)別是:互斥鎖中,調(diào)用者在別的運算單元搶占鎖后進(jìn)入睡眠,等待結(jié)束后被喚醒進(jìn)行搶占;自旋鎖,調(diào)用者在被運算單元搶占鎖后不睡眠,循環(huán)查看自旋鎖是否被釋放。
故自旋鎖適合保持鎖時間較短的情況,這種情況下其效率遠(yuǎn)高于互斥鎖。
缺點:需要獲取鎖的線程優(yōu)先級相同。如果低優(yōu)先級的線程獲得鎖后,高優(yōu)先級線程會處于busy-wait狀態(tài),占用大量CPU。而低優(yōu)先級線程無法獲取CPU時間,導(dǎo)致任務(wù)無法完成,也就無法釋放鎖。造成死鎖(優(yōu)先級反轉(zhuǎn))。
參考資料: