互斥鎖 解決原子性問題

2021-10-13 07:50:05 字數 1271 閱讀 5735

原子性:乙個或多個操作在cpu執行的過程中不被中斷的特性

原子性問題的源頭是執行緒切換,作業系統做執行緒切換依賴於cpu中斷,所以禁止cpu中斷就能禁止執行緒切換。

示例:在32位cpu上執行long型別變數的寫操作,long型別變數是64位,所以會被拆分為兩次寫操作(寫高32位和寫低32位)

1.單核cpu場景下,同一時刻只有乙個執行緒在執行,禁止cpu中斷,意味著作業系統不會重新排程執行緒,也就是禁止了執行緒切換,獲得cpu使用權的執行緒就可以不間斷執行,所以兩次寫操作,要麼都被執行,要麼都沒有被執行,具備原子性。

2.多核cpu場景下,同一時刻有可能有兩個執行緒在同時執行,乙個執行緒執行在cpu-1上,乙個執行緒執行在cpu-2上,此時禁止cpu中斷,只能保證cpu上的執行緒連續執行,不能保證同一時刻只有乙個執行緒在執行,如果兩個執行緒同時寫long型別變數的高32位,就會出現bug。

互斥:同一時刻只有乙個執行緒在執行。若能保證對共享變數的修改是互斥的,無論是單核cpu或者多核cpu,都能夠保證原子性。

鎖模型synchronized

class x 

// 修飾靜態方法

synchronized static void bar()

// 修飾**塊

object obj = new object();

void baz()

}}

當修飾靜態方法的時候,鎖定的是當前類的class物件;

當修飾非靜態方法的時候,鎖定的是當前例項物件this;

class x 

// 修飾靜態方法

synchronized(x.class) static void bar()

}

細粒度鎖:用不同的鎖對受保護的資源進行精細化管理,能夠提公升效能。

轉賬**

class account } }

怎麼保證轉賬操作沒有併發問題?

誤區:直接加synchronized

class account } }

問題原因:this這把鎖只能保護自己的餘額this.balance,保護不了別人的餘額target.balance

正確方案:用account.class 作為共享的鎖

class account }} 

}

缺點:用account.class作為鎖,則所有的轉賬操作穿行化了。

互斥鎖,解決原子性問題以及加鎖後引發的死鎖

互斥鎖,解決原子性問題以及加鎖後引發的死鎖 原子性的問題就是執行緒切換。在單核時代,同一時刻只有乙個執行緒工作,禁用cpu中斷就能禁止執行緒切換。多核時代,同一時刻可能有多個執行緒在執行,禁用cpu中斷並不能解決原子性問題。經過上述分析得出結論,同一時刻只有乙個執行緒執行是解決原子性問題的必要條件,...

Golang 原子操作與互斥鎖

先來看乙個 package main import fmt runtime sync var counter int32 wg sync.waitgroup func main func addcounter whoami string final counter is 2 首先這個程式是起了兩個 ...

C 互斥量 原子鎖 自旋鎖等比較

現象 1 單執行緒無鎖速度最快,但應用場合受限 2 多執行緒無鎖速度第二快,但結果不對,未保護臨界 段 3 多執行緒原子鎖第三快,且結果正確 4 多執行緒互斥量較慢,慢與原子鎖近10倍,結果正確 5 多執行緒自旋鎖最慢,慢與原子鎖30倍,結果正確。結論 原子鎖速度最快,互斥量和自旋鎖都用保護多執行緒...