自旋鎖和互斥鎖實例_多線程編程之自旋鎖

一、什么是自旋鎖

一直以為自旋鎖也是用于多線程互斥的一種鎖,原來不是!

自旋鎖是專為防止多處理器并發(實現保護共享資源)而引入的一種鎖機制。自旋鎖與互斥鎖比較類似,它們都是為了解決對某項資源的互斥使用。無論是互斥鎖,還是自旋鎖,在任何時刻,最多只能有一個保持者,也就說,在任何時刻最多只能有一個執行單元獲得鎖。但是兩者在調度機制上略有不同。對于互斥鎖,如果資源已經被占用,資源申請者只能進入睡眠狀態。但是自旋鎖不會引起調用者睡眠,如果自旋鎖已經被別的執行單元保持,調用者就一直循環在那里看是否該自旋鎖的保持者已經釋放了鎖,“自旋”一詞就是因此而得名。自旋鎖在內核中大量應用于中斷處理等部分(對于單處理器來說,防止中斷處理中的并發可簡單采用關閉中斷的方式,即在標志寄存器中關閉/打開中斷標志位,不需要自旋鎖)。

自旋鎖的初衷就是:在短期間內進行輕量級的鎖定。一個被爭用的自旋鎖使得請求它的線程在等待鎖重新可用的期間進行自旋(特別浪費處理器時間),所以自旋鎖不應該被持有時間過長。如果需要長時間鎖定的話,?最好使用信號量。

自旋鎖只有在內核可搶占或SMP(多處理器)的情況下才真正需要,在單CPU且不可搶占的內核下,自旋鎖的所有操作都是空操作。

二、自旋鎖的缺陷

自旋鎖是一種比較低級的保護數據結構或代碼片段的原始方式,這種鎖可能存在兩個問題:

(1)死鎖。試圖遞歸地獲得自旋鎖必然會引起死鎖:例如遞歸程序的持有實例在第二個實例循環,以試圖獲得相同自旋鎖時,就不會釋放此自旋鎖。所以,在遞歸程序中使用自旋鎖應遵守下列策略:遞歸程序決不能在持有自旋鎖時調用它自己,也決不能在遞歸調用時試圖獲得相同的自旋鎖。此外如果一個進程已經將資源鎖定,那么,即使其它申請這個資源的進程不停地瘋狂“自旋”,也無法獲得資源,從而進入死循環。

(2)過多占用cpu資源。如果不加限制,由于申請者一直在循環等待,因此自旋鎖在鎖定的時候,如果不成功,不會睡眠,會持續的嘗試,單cpu的時候自旋鎖會讓其它process動不了。因此,一般自旋鎖實現會有一個參數限定最多持續嘗試次數。超出后,自旋鎖放棄當前time slice,等下一次機會。

由此可見,自旋鎖比較適用于鎖使用者保持鎖時間比較短的情況。正是由于自旋鎖使用者一般保持鎖時間非常短,因此選擇自旋而不是睡眠是非常必要的,自旋鎖的效率遠高于互斥鎖。信號量和讀寫信號量適合于保持時間較長的情況,它們會導致調用者睡眠,因此只能在進程上下文使用,而自旋鎖適合于保持時間非常短的情況,它可以在任何上下文使用。

三、Linux環境下的自旋鎖

自旋鎖的實現基于共享變量。一個線程通過給共享變量設置一個值來獲取鎖,其他等待線程查詢共享變量是否為0來確定鎖現是否可用,然后在忙等待的循環中“自旋”直到鎖可用為止。自旋鎖的狀態值為1表示解鎖狀態,說明有1個資源可用;0或負值表示加鎖狀態,0說明可用資源數為0。Linux內核為通用自旋鎖提供了API函數初始化、測試和設置自旋鎖。API函數功能說明如下表所示:

宏定義

功能說明

spin_lock_init(lock)

初始化自旋鎖,將自旋鎖設置為1,表示有一個資源可用。

spin_is_locked(lock)

如果自旋鎖被置為1(未鎖),返回0,否則返回1。

spin_unlock_wait(lock)

等待直到自旋鎖解鎖(為1),返回0;否則返回1。

spin_trylock(lock)

嘗試鎖上自旋鎖(置0),如果原來鎖的值為1,返回1,否則返回0。

spin_lock(lock)

循環等待直到自旋鎖解鎖(置為1),然后,將自旋鎖鎖上(置為0)。

spin_unlock(lock)

將自旋鎖解鎖(置為1)。

spin_lock_irqsave(lock, flags)

循環等待直到自旋鎖解鎖(置為1),然后,將自旋鎖鎖上(置為0)。關中斷,將狀態寄存器值存入flags。

spin_unlock_irqrestore(lock, flags)

將自旋鎖解鎖(置為1)。開中斷,將狀態寄存器值從flags存入狀態寄存器。

spin_lock_irq(lock)

循環等待直到自旋鎖解鎖(置為1),然后,將自旋鎖鎖上(置為0)。關中斷。

spin_unlock_irq(lock)

將自旋鎖解鎖(置為1)。開中斷。

spin_unlock_bh(lock)

將自旋鎖解鎖(置為1)。開啟底半部的執行。

spin_lock_bh(lock)

循環等待直到自旋鎖解鎖(置為1),然后,將自旋鎖鎖上(置為0)。阻止軟中斷的底半部的執行。

在實際編程中,何時使用spin_lock,何時使用spin_lock_irq呢?這兩者有點區別。

(1)spin_lock

spin_lock 的實現關系為:spin_lock ->?raw_spin_lock ->?_raw_spin_lock ->?__raw_spin_lock ,而__raw_spin_lock?的實現為:

static inline void __raw_spin_lock(raw_spinlock_t *lock)

{

preempt_disable();

spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);

LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);

}

(2)spin_lock_irq

spin_lock_irq 的實現關系為:spin_lock_irq ->?raw_spin_lock_irq ->?_raw_spin_lock_irq ->?__raw_spin_lock_irq,而__raw_spin_lock_irq 的實現為:

static inline void __raw_spin_lock_irq(raw_spinlock_t *lock)

{

local_irq_disable();

preempt_disable();

spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);

LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);

}

由此可見,這兩者之間只有一個差別:是否調用local_irq_disable()函數, 即是否禁止本地中斷。這兩者的區別可以總結為:

在任何情況下使用spin_lock_irq都是安全的。因為它既禁止本地中斷,又禁止內核搶占。

spin_lock比spin_lock_irq速度快,但是它并不是任何情況下都是安全的。

舉例來說明:進程A中調用了spin_lock(&lock)然后進入臨界區,此時來了一個中斷(interrupt),該中斷也運行在和進程A相同的CPU上,并且在該中斷處理程序中恰巧也會spin_lock(&lock)試圖獲取同一個鎖。由于是在同一個CPU上被中斷,進程A會被設置為TASK_INTERRUPT狀態,中斷處理程序無法獲得鎖,會不停的忙等,由于進程A被設置為中斷狀態,schedule()進程調度就無法再調度進程A運行,這樣就導致了死鎖!但是如果該中斷處理程序運行在不同的CPU上就不會觸發死鎖。 因為在不同的CPU上出現中斷不會導致進程A的狀態被設為TASK_INTERRUPT,只是換出。當中斷處理程序忙等被換出后,進程A還是有機會獲得CPU,執行并退出臨界區。所以在使用spin_lock時要明確知道該鎖不會在中斷處理程序中使用。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/538159.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/538159.shtml
英文地址,請注明出處:http://en.pswp.cn/news/538159.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

如何卸載symantec

前段時間,業務的虛機上安裝了symantec Endpoint Protection(正版), 發現虛機運行一段時間就會失去響應死機,并且有些安裝symantec的虛機3389端口無法使用,怎么折騰都不行。最后決定卸載它。一、是否可以用停止服務和終止進程再卸載的方式卸載…

CSS文件引入順序

<link rel"stylesheet" href"bootstrap.min.css"> <link rel"stylesheet" href"app.css"> 自定義的css要最后引入。因為有時候會修改bootstrap的css。只有后引入的才會覆蓋。 如果提前引入了&#xff0c;自定義的會被bo…

瀏覽器的簡單兼容

2019獨角獸企業重金招聘Python工程師標準>>> function getXHER() { var xhr null; if(XMLHttpRequest){ xhr new XMLHttpRequest(); }else{ xhr new ActiveXObject(Microsoft.XMLHTTP); } return xhr; }轉載于:https://my.oschina.net/u/2511906/blog/1865622

用計算機算出陳赫手機號碼,陳赫手機號碼遭《快本》曝光,并被網友打到關機!還有人搜到了他的支付寶賬戶......

原標題&#xff1a;陳赫手機號碼遭《快本》曝光&#xff0c;并被網友打到關機&#xff01;還有人搜到了他的支付寶賬戶...昨天的陳赫可能是被不斷的電話鈴聲叫醒的&#xff0c;因為快本在節目中把陳赫的電話號碼給曝光了……當時導演讓每個明星向自己的一位圈內好友發出求助短信…

伯努利分布方差_統計分布--深入淺出統計學總結

伯努利分布&#xff1a;一個實驗只有兩個結果概率發生在{0,1}&#xff0c;發生一個事件成功的概率為 x&#xff0c;不成功的概率為y&#xff0c; 1.若符合伯努基分布條件&#xff1a;p 成功概率 &#xff0c; q 失敗概率伯努利分布數學期待&#xff1a;伯努利分布方差&#x…

解決The project description file (.project) for 'xxx' is missing

若沒有修改過.project文件&#xff0c;只需重新導入工程即可&#xff0c;別糾結其他的了

macbook禁用鍵盤_一行命令禁用 MacBook 內置鍵盤

去年底阿麥換了新的 MacBook Pro&#xff0c;于是她自學生時代就一直在用的老款 MacBook Pro 就歸我當玩具了。一度考慮過將其出售&#xff0c;但是想到自己還閑置了一塊 SSD&#xff0c;就想著干脆換上讓它繼續服役。于是買了光驅硬盤支架&#xff0c;想著有時間就給換上。然而…

Java分享筆記:自定義枚舉類 使用enum關鍵字定義枚舉類

在JDK1.5之前沒有enum關鍵字&#xff0c;如果想使用枚舉類&#xff0c;程序員需要根據Java語言的規則自行設計。從JDK1.5開始&#xff0c;Java語言添加了enum關鍵字&#xff0c;可以通過該關鍵字方便地定義枚舉類。這種枚舉類有自己的程序編寫規則&#xff0c;并且具有一些特殊…

html5做咖啡網頁素材,HTML5/CSS3咖啡品類切換動畫

CSS語言&#xff1a;CSSSCSS確定body {background-color: #FB9F89;}.container {position: absolute;top: 30px;left: 200px;}.saucer {position: absolute;top: 50px;left: 40px;width: 200px;height: 200px;border-radius: 100%;background-color: #FFF;box-shadow: 5px 1px …

汽車和山羊問題matlab仿真_Matlab----無人機集群對抗中的關鍵問題和仿真平臺(開發中)案例...

無人機集群對抗&#xff0c;是自動駕駛中路徑規劃的新問題&#xff0c;并且連續兩年出現在最近的中國大學生數學建模競賽中。可見&#xff0c;這是一個急需解決的數學問題&#xff08;體現了官方的軍事戰略意志&#xff09;&#xff0c;同時&#xff0c;還沒有成熟解決方案的問…

使用durid的ConfigFilter對數據庫密碼加密

原文連接&#xff1a;http://blog.csdn.net/aixiaoyang168/article/details/49930513 ----------------------------------------------------------------------- 對于大部分程序員來說&#xff0c;數據庫的信息&#xff0c;如用戶名&#xff0c;密碼等信息一般都寫到配置文件…

序(不知道是什么時候的模擬題)

序 【問題背景】 zhx 給他的妹子們排序。 【問題描述】 \(zhx\) 有 \(N\) 個妹子&#xff0c; 他對第 \(i\) 個妹子的好感度為\(a_i\), 且所有\(a_i\),兩兩不相等。 現在 \(N\) 個妹子隨意站成一排&#xff0c; 他要將她們根據好感度從小到大排序。 他使用的是冒泡排序算法&…

html寫用戶導入,用戶基本信息錄入.html

&#xfeff;用戶基本信息錄入$axure.utils.getTransparentGifPath function() { return resources/images/transparent.gif; };$axure.utils.getOtherPath function() { return resources/Other.html; };$axure.utils.getReloadPath function() { return resources/reload.…

adg oracle 架構_技術棧數據中心有了ADG架構就高枕無憂了?你還需要做這一步!...

技術棧數據中心有了ADG架構&#xff0c;就高枕無憂了&#xff1f;你還需要做這一步&#xff01;如果把數據中心建設比喻成西天取經&#xff0c;那旅途上的九九八十一難就是我們不得不躲閃、跨越、攻堅的堡壘。即日起&#xff0c;希嘉推出“技術棧”板塊&#xff0c;集結數據治理…

String length must be a multiple of four.

今天在整理2013年的工作時的一個項目&#xff0c;修改了數據庫連接&#xff0c;初始化數據庫&#xff0c;部署運行報錯&#xff0c;主要原因是阿里巴巴druid報錯&#xff0c;導致DataSource初始化失敗。 druid報錯日志&#xff1a; Caused by: java.lang.IllegalArgumentExce…

論文筆記:Person Re-identification with Deep Similarity-Guided Graph Neural Network

Person Re-identification with Deep Similarity-Guided Graph Neural Network 2018-07-27 17:41:45 Paper&#xff1a; https://128.84.21.199/pdf/1807.09975.pdf 本文將 Graph Neural Network (GNN) 應用到 person re-ID 的任務中&#xff0c;用于 model 不同 prob-gallery …

CGLib動態代理原理及實現

原文連接&#xff1a;http://songbo-mail-126-com.iteye.com/blog/968792 ------------------------------------------------------------------------ JDK實現動態代理需要實現類通過接口定義業務方法&#xff0c;對于沒有接口的類&#xff0c;如何實現動態代理呢&#xff…

微型計算機的硬件組成中ssd硬盤通常是指,2015年計算機一級msoffice選擇題121道及答案...

31、通常&#xff0c;在微機中標明的P4或奔騰4是指( D )A、產品型號B、主頻C、微機名稱D、微處理器型號32、以平均無故障時間(MTBF)&#xff0c;用于描述計算機的( A )A、可靠性B、可維護性C、性能價格比D、以上答案都不對33、以平均修復時間(MTTR)&#xff0c;用于描述計算機的…

雙曲函數奇偶性_基本初等函數之奇偶性(強基系列42)

基本初等函數之奇偶性(強基系列4-2)開卷有益初等函數是由冪函數(power function)、指數函數(exponential function)、對數函數(logarithmic function)、三角函數(trigonometric function)、反三角函數(inverse trigonometric function)與常數經過有限次的有理運算(加、減、乘、…

Caused by: Parent package is not defined: json-default - [unknown location]

原文連接&#xff1a;http://blog.csdn.net/bebested/article/details/52627890 ------------------------------------------------------------------------------------------- Unable to load configuration. - [unknown location] at com.opensymphony.xwork2.config.Co…