線程安全的本質是正確性,而正確性的含義是程序按照預期執行java
理論上線程安全的程序,應該要避免出現可見性問題(CPU緩存)、原子性問題(線程切換)和有序性問題(編譯優化)算法
須要分析是否存在線程安全問題的場景:存在共享數據且數據會發生變化,即有多個線程會同時讀寫同一個數據緩存
數據競爭(Data Race):多個線程同時訪問同一數據,而且至少有一個線程會寫這個數據安全
1. addbash
private static final int MAX_COUNT = 1_000_000;
private long count = 0;
// 非線程安全
public void add() {
int index = 0;
while (++index < MAX_COUNT) {
count += 1;
}
}複製代碼
2. add + synchronized數據結構
private static final int MAX_COUNT = 1_000_000;
private long count = 0;
public synchronized long getCount() {
return count;
}
public synchronized void setCount(long count) {
this.count = count;
}
// 非線程安全
public void add() {
int index = 0;
while (++index < MAX_COUNT) {
setCount(getCount() + 1);
}
}複製代碼
1. 轉帳多線程
public class Account {
private int balance;
// 非線程安全,存在竟態條件,可能會超額轉出
public void transfer(Account target, int amt) {
if (balance > amt) {
balance -= amt;
target.balance += amt;
}
}
}複製代碼
面對數據競爭和竟態條件問題,能夠經過互斥的方案來實現線程安全,互斥的方案能夠統一歸爲鎖併發
活躍性問題:某個操做沒法執行下去,包括三種狀況:死鎖、活鎖、飢餓分佈式
喜歡的能夠關注個人公衆號,java小瓜哥的分享平臺,平時整理的資料都放在裏面了性能