編寫線程安全需要關心的:
1.共享的變數
2.可變的變數
共享意味著多個執行緒可以同時訪問,可變意味著其值在生命週期可以改變。
例如以下count 變數:
複製代碼代碼如下:
//線程不安全的類
public class UnsafeCount {
private int count = 0; //該變數是共享的
public void increase() { //這裡沒有同步機制,多個執行緒可以同時存取
count++; //該變數是可變的
}
public int getCount() {
return count;
}
}
有4種方式可以修復這個問題:
1.不在執行緒中共享該狀態變量,可以將變數封裝到方法中(無狀態的物件一定是執行緒安全的);因為方法中變數是每個執行緒獨佔的,不和其它執行緒共享。比如:
複製代碼代碼如下:
public int add(int count){
return ++count;//這裡也可以說無狀態的物件一定是線程安全的
}
2.將狀態變數修改為不可變的變數。
複製代碼代碼如下:
private final int count = 0;
3.在存取狀態變數使用同步策略。
複製代碼代碼如下:
public synchronized void increase() {
count++;
}
4.使用原子變數類別。
複製代碼代碼如下:
private AtomicInteger count;
public void increase() {
count.getAndAdd(1);
}