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