自旋锁/互斥锁/读写锁/递归锁的区别与联系
自旋鎖 互斥鎖 讀寫鎖 遞歸鎖
?
?
?
互斥鎖(mutexlock):
?
最常使用于線程同步的鎖;標(biāo)記用來保證在任一時刻,只能有一個線程訪問該對象,同一線程多次加鎖操作會造成死鎖;臨界區(qū)和互斥量都可用來實現(xiàn)此鎖,通常情況下鎖操作失敗會將該線程睡眠等待鎖釋放時被喚醒
自旋鎖(spinlock):
同樣用來標(biāo)記只能有一個線程訪問該對象,在同一線程多次加鎖操作會造成死鎖;使用硬件提供的swap指令或test_and_set指令實現(xiàn);同互斥鎖不同的是在鎖操作需要等待的時候并不是睡眠等待喚醒,而是循環(huán)檢測保持者已經(jīng)釋放了鎖,這樣做的好處是節(jié)省了線程從睡眠狀態(tài)到喚醒之間內(nèi)核會產(chǎn)生的消耗,在加鎖時間短暫的環(huán)境下這點會提高很大效率
讀寫鎖(rwlock):
高級別鎖,區(qū)分讀和寫,符合條件時允許多個線程訪問對象。處于讀鎖操作時可以允許其他線程和本線程的讀鎖, 但不允許寫鎖, 處于寫鎖時則任何鎖操作都會睡眠等待;常見的操作系統(tǒng)會在寫鎖等待時屏蔽后續(xù)的讀鎖操作以防寫鎖被無限孤立而等待,在操作系統(tǒng)不支持情況下可以用引用計數(shù)加寫優(yōu)先等待來用互斥鎖實現(xiàn)。 讀寫鎖適用于大量讀少量寫的環(huán)境,但由于其特殊的邏輯使得其效率相對普通的互斥鎖和自旋鎖要慢一個數(shù)量級;值得注意的一點是按POSIX標(biāo)準(zhǔn)?在線程申請讀鎖并未釋放前本線程申請寫鎖是成功的,但運行后的邏輯結(jié)果是無法預(yù)測
遞歸鎖(recursivelock):
嚴(yán)格上講遞歸鎖只是互斥鎖的一個特例,同樣只能有一個線程訪問該對象,但允許同一個線程在未釋放其擁有的鎖時反復(fù)對該鎖進行加鎖操作; windows下的臨界區(qū)默認(rèn)是支持遞歸鎖的,而linux下的互斥量則需要設(shè)置參數(shù)PTHREAD_MUTEX_RECURSIVE_NP,默認(rèn)則是不支持
大讀者鎖(brlock-Big Reader Lock)
?
大讀者鎖是讀寫鎖的高性能版,讀者可以非常快地獲得鎖,但寫者獲得鎖的開銷比較大。大讀者鎖只存在于2.4內(nèi)核中,在2.6中已經(jīng)沒有這種鎖(提醒讀者特別注意)。它們的使用與讀寫鎖的使用類似,只是所有的大讀者鎖都是事先已經(jīng)定義好的。這種鎖適合于讀多寫少的情況,它在這種情況下遠(yuǎn)好于讀寫鎖。
大讀者鎖的實現(xiàn)機制是:每一個大讀者鎖在所有CPU上都有一個本地讀者寫者鎖,一個讀者僅需要獲得本地CPU的讀者鎖,而寫者必須獲得所有CPU上的鎖。
大讀者鎖的API非常類似于讀寫鎖,只是鎖變量為預(yù)定義的鎖ID。
大內(nèi)核鎖(BKL--Big Kernel Lock)
大內(nèi)核鎖本質(zhì)上也是自旋鎖,但是它又不同于自旋鎖,自旋鎖是不可以遞歸獲得鎖的,因為那樣會導(dǎo)致死鎖。但大內(nèi)核鎖可以遞歸獲得鎖。大內(nèi)核鎖用于保護整個內(nèi)核,而自旋鎖用于保護非常特定的某一共享資源。進程保持大內(nèi)核鎖時可以發(fā)生調(diào)度,具體實現(xiàn)是:在執(zhí)行schedule時,schedule將檢查進程是否擁有大內(nèi)核鎖,如果有,它將被釋放,以致于其它的進程能夠獲得該鎖,而當(dāng)輪到該進程運行時,再讓它重新獲得大內(nèi)核鎖。注意在保持自旋鎖期間是不運行發(fā)生調(diào)度的。
需要特別指出,整個內(nèi)核只有一個大內(nèi)核鎖,其實不難理解,內(nèi)核只有一個,而大內(nèi)核鎖是保護整個內(nèi)核的,當(dāng)然有且只有一個就足夠了。
還需要特別指出的是,大內(nèi)核鎖是歷史遺留,內(nèi)核中用的非常少,一般保持該鎖的時間較長,因此不提倡使用它。從2.6.11內(nèi)核起,大內(nèi)核鎖可以通過配置內(nèi)核使其變得可搶占(自旋鎖是不可搶占的),這時它實質(zhì)上是一個互斥鎖,使用信號量實現(xiàn)。
?
RCU(Read-Copy Update)
RCU(Read-Copy Update),顧名思義就是讀-拷貝修改,它是基于其原理命名的。對于被RCU保護的共享數(shù)據(jù)結(jié)構(gòu),讀者不需要獲得任何鎖就可以訪問它,但寫者在訪問它時首先拷貝一個副本,然后對副本進行修改,最后使用一個回調(diào)(callback)機制在適當(dāng)?shù)臅r機把指向原來數(shù)據(jù)的指針重新指向新的被修改的數(shù)據(jù)。這個時機就是所有引用該數(shù)據(jù)的CPU都退出對共享數(shù)據(jù)的操作。
RCU也是讀寫鎖的高性能版本,但是它比大讀者鎖具有更好的擴展性和性能。 RCU既允許多個讀者同時訪問被保護的數(shù)據(jù),又允許多個讀者和多個寫者同時訪問被保護的數(shù)據(jù)(注意:是否可以有多個寫者并行訪問取決于寫者之間使用的同步機制),讀者沒有任何同步開銷,而寫者的同步開銷則取決于使用的寫者間同步機制。但RCU不能替代讀寫鎖,因為如果寫比較多時,對讀者的性能提高不能彌補寫者導(dǎo)致的損失。
?
順序鎖(seqlock)
順序鎖也是對讀寫鎖的一種優(yōu)化,對于順序鎖,讀者絕不會被寫者阻塞,也就說,讀者可以在寫者對被順序鎖保護的共享資源進行寫操作時仍然可以繼續(xù)讀,而不必等待寫者完成寫操作,寫者也不需要等待所有讀者完成讀操作才去進行寫操作。但是,寫者與寫者之間仍然是互斥的,即如果有寫者在進行寫操作,其他寫者必須自旋在那里,直到寫者釋放了順序鎖。
這種鎖有一個限制,它必須要求被保護的共享資源不含有指針,因為寫者可能使得指針失效,但讀者如果正要訪問該指針,將導(dǎo)致OOPs。
如果讀者在讀操作期間,寫者已經(jīng)發(fā)生了寫操作,那么,讀者必須重新讀取數(shù)據(jù),以便確保得到的數(shù)據(jù)是完整的。
這種鎖對于讀寫同時進行的概率比較小的情況,性能是非常好的,而且它允許讀寫同時進行,因而更大地提高了并發(fā)性。
總結(jié)
以上是生活随笔為你收集整理的自旋锁/互斥锁/读写锁/递归锁的区别与联系的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: cpu224xp生产方案
- 下一篇: 程序员面试的一些注意点