標籤:複合 封裝 自動 因此 協議 之間 對象 寫入 物件導向
1.競態條件
1.1 定義當某個計算的正確性取決於多個線程的交替執行時序時,就會發生競態條件。換句話說,正確的結果要取決於運氣。最常見的競態條件類型:先檢查後執行(Check-Then-Act)操作,即通過一個可能失效的觀測結果來決定下一步的動作。
1.2 特徵與大多數並發錯誤一樣,競態條件並不總是會產生錯誤,還需要某種不恰當的執行時序。
1.3 複合操作為了確保執行緒安全性,“先檢查後執行”(例如延遲初始化)和“讀取-修改-寫入”等操作統稱為複合操作:包含了一組必須以原子方式執行的操作以確保執行緒安全性。
2 加鎖機制
2.1線上程安全性定義中要求,多個線程之間的操作無論採用合種執行時序或交替方式,都要保證不變性條件不被破壞。當在不變性條件中涉及多個變數時,各個變數之間並不是彼此獨立的,而是某個變數的值會對其他變數的值產生約束。因此,當更新某一個變數時,需要在同一個原子操作中對其他變數同時進行更新。
2.2 內建鎖Java提供了一種內建的鎖機制來支援原子性:同步代碼塊(Synchronized Block)。同步代碼塊包括兩部分:一個作為鎖的對象引用,一個作為由這個鎖保護的代碼塊。每個Java對象都可以用作一個實現同步的鎖,這些鎖被稱為內建鎖(Intrinsic Lock)或監視器鎖(Monitor Lock)。線程在進入同步代碼塊之前會自動獲得鎖,並且在退出同步代碼塊時自動釋放鎖,而無論是通過正常的控制路徑退出,還是通過從代碼塊中拋出異常退出。獲得內建鎖的唯一途徑就是進入由這個鎖保護的同步代碼塊或方法。 Java的內建鎖相當於一種互斥體(或互斥鎖),這意味著最多隻有一個線程能持有這種鎖。 當線程A嘗試擷取一個由線程B持有的鎖時,線程A必須等待或阻塞,直到線程B釋放這個鎖。如果B永遠不釋放鎖,那麼A也將永遠地等待下去。
2.3 鎖的重入如果某個線程試圖獲得一個已經由它自己持有的鎖,那麼請求就會成功。重入進一步提升了加鎖行為的封裝性,因此簡化了物件導向並發代碼的開發。
2.4 用鎖來保護狀態由於鎖能使其保護的代碼路徑以串列形式來訪問,因此可以通過鎖來構造一些協議以實現對共用狀態的獨佔訪問。只要始終遵循這些協議,就能確保狀態的一致性。
2.5 不良並發(Poor Concurrency)應用程式:可同時調用的數量,不僅受到可用處理資源的限制,還受到應用程式本身結構的限制:任意一個請求均需要等待前一個請求執行完成。 確保並發的同時維護執行緒安全性:縮小同步代碼塊的範圍,並盡量避免將IO等耗時操作加在同步代碼塊中。
Java並發編程入門(二)