線程安全性(第二章)
線程安全性
要編寫線程安全的代碼,其核心在於要對狀態訪問操作進行管理,特別是對共享的(Shared)和可變的(Mutable)狀態的訪問。
- 對象的狀態:存儲在狀態變量(例如實例或靜態域)中的數據,包括其他以來對象的域
- 共享(Shared):意味著變量可以由多個線程同時訪問
- 可變(Mutable):變量的值在其生命周期內可以發生變化
一個對象是否需要使線程安全的,取決於它是否被多個線程訪問。這指的是在程序中訪問對象的方式,而不是對象要實現的功能。要使得對象是線程安全的,需要采用同步機製來協同對對象可變狀態的訪問。如果無法實現協同,那麼可能會導致數據破壞以及其他不該出現的結果。
1. 什麼是線程安全性:
在線程安全性的定義中,最核心的概念就是正確性。當多個線程訪問某個類時,這個類始終都能表現出正確地行為,那麼就稱這個類是線程安全的。
- 線程安全性特例:**無狀態類一定是線程安全的**
2. 原子性
-
競態條件(Race condition):由於不恰當的執行時序而出現不正確地結果
最常見的靜態條件就是“先檢查後執行”(可能導致通過一個失效的觀測結果來決定下一步的動作)不要將“競態條件”與“數據競爭”相混淆,數據競爭是指,如果在訪問共享的非final類型的域沒有采用同步來進行協同,那麼就會出現數據競爭。
要保持狀態的一致性,就需要在單個原子操作中更新所有相關的狀態變量。
3.加鎖機製
Java中的內置鎖(synchronized)是可重入的,即已獲得鎖的線程可以再次獲得這個鎖。
對於可能被多個線程同時訪問的可變狀態變量,在訪問它時都需要持有同一個鎖,在這種情況下,我們稱狀態變量是由這個鎖保護的。
一種常見的錯誤認為:隻有在寫入共享變量時才需要使用同步。這是錯誤的。
最後更新:2017-11-04 17:33:39