事務基礎 事務 事務 是一組操作的集合,它是一個不可分割的工作單位,事務會把所有的操作作為一個整體一起向系統提交或撤銷操作請求,即這些操作要麼同時成功,要麼同時失敗。 特性 原子性(Atomicity):事務是不可分割的最小操作單元,要麼全部成功,要麼全部失敗。 一致性(Consistency):事 ...
Java併發小結01
主要參考自《實戰Java高併發程式設計》。
需要知道的概念
- 同步與非同步
- 併發與並行
- 臨界區
- 阻塞與非阻塞
- 死鎖、饑餓、活鎖
同步與非同步
同步:同步方法一旦被調用,必須等待方法返回後才能繼續後續的行為。
非同步:非同步方法就像一個消息傳遞,被調用後方法會立即返回,調用者可以開始後續的行為。
併發與並行
並行:兩個任務同時執行。
併發:一段時間內,多個任務在CPU交替執行,看似並行。
臨界區
用來表示一種可以被多個線程使用的公共資源,但是一次只能一個線程使用。一旦臨界區被占用,其他線程只能等待。
比如說印表機:一次只能列印一份文件,要是交替列印,那麼列印出來的東西是不可用的。
阻塞與非阻塞
阻塞:一個線程占用了臨界區資源,其他線程需要這個資源就得等待,等待會導致線程掛起,這就是阻塞。
非阻塞:與阻塞相反,沒有一個線程可以導致其他線程阻塞,所有線程都不斷嘗試繼續執行。
死鎖、饑餓、活鎖
死鎖:兩個或兩個以上線程相互請求其他線程的資源,誰都執行不下去。
饑餓:一個線程因為種種原因一直獲取不到需要的資源導致無法執行。
活鎖:線程之間將資源相互推讓而沒有一個線程拿到資源繼續執行。
併發級別
- 阻塞
- 無饑餓
- 無障礙
- 無鎖
- 無等待
阻塞
使用synchronized關鍵字或重入鎖,得到的就是阻塞的線程。
無饑餓
線程預設是不公平的(理論上優先滿足優先順序高的),會導致饑餓,公平鎖解決饑餓問題。
無障礙
無障礙是一種最弱的非阻塞調度。兩個線程如果無障礙地運行,那麼不會因為臨界區的問題導致一方被掛起。如果數據壞了就回滾,沒有數據競爭就順利完成工作,走出臨界區。
無障礙有可能會因為數據衝突一直回滾,一種可行的無障礙實現可以依賴一個“一致性標記”來實現。
無鎖
無鎖的並行都是無障礙的。無鎖的狀態下,所有的線程都能嘗試對臨界區進行訪問,不同的是,無鎖的併發保證必然有一個線程能夠在有限步內完成操作離開臨界區。
會出現線程饑餓。
無鎖的特點:可能會包含一個無窮迴圈。在這個迴圈中,線程會不斷地嘗試修改共用變數。如果沒有衝突,修改成功,走人,否則繼續嘗試。
無等待
無鎖只要求有一個線程在有限步內完成操作,而無等待則在無鎖的基礎上更近一步擴展。它要求所有線程都必須在有限步數內完成,這樣就不會引起饑餓問題。
JMM
探討一下java記憶體模型:原子性、可見性、有序性。
原子性:
一個操作是不可中斷的。
可見性
一個線程修改了某個共用變數的值時,其他線程會立馬知道這個修改。
有序性
程式在執行時,可能就進行指令排序,排序後的指令順序與原指令順序未必一致。
但是指令排序可以保證串列語義一致,不保證並行語義一致。
那些指令不能排序:Happen-Before原則
-
程式順序原則:一個線程內保證語義的串列性。
-
volatile 原則:volatile變數的寫先於讀發生,這保證了volatile變數的可見性。
-
鎖規則:解鎖(unlock)必然發生在隨後的加鎖(lock)前面。
-
傳遞性:A先於B,B先於C,那麼A先於C。
-
線程的start()方法先於它的每一個動作。
-
線程的中斷(interrupt)先於被中斷線程的代碼。
-
對象的構造函數的執行、結束先於finalize()方法。
個人小結:
這些都是概念性問題,如果第一次不太熟悉可以baidu一下進行理解。
作為《實戰Java高併發程式設計》的一章,主要介紹了併發的一些概念性關鍵詞,建議深入理解,後面的多線程併發操作都建立在這些概念之上。
其中第一章有一個小結介紹有關並行的兩個定律我忽略了,感興趣的可以自己去看: Amdahl定律和Gustafson定律。