第二章 執行緒安全性

1-什麼是執行緒安全的類?

當多個執行緒訪問某一個類時,不管執行時環境採用何種排程方式或者這些執行緒將如何交替執行,並且在主調程式碼中不需要任何額外的同步或協同,這個類都能表現出正確的行為,那麼就稱這個類是執行緒安全的

2-如何保證執行緒安全?

  1. 不線上程之間共享該狀態變數
  2. 將狀態變數修改為不可變的變數
  3. 在訪問狀態變數時使用同步

無狀態的物件一定是執行緒安全的

3、什麼是競態條件?什麼是資料競爭?

競態條件:當某個計算結果的正確性取決於多個執行緒的交替執行時序時,那麼就會發生競態條件

資料競爭:如果在訪問共享的非final型別的域時沒有采用同步來進行協同,那麼就會出現資料競爭,當一個執行緒寫入一個變數而另一個執行緒接下來讀取這個變數,或者讀取一個之前由另一個執行緒寫入的變數時,並且在這兩個執行緒之間沒有使用同步,那麼就會出現資料競爭

4、什麼是內建鎖?

每個Java物件都可以用作一個實現同步的鎖,這些鎖被稱為內建鎖或者監視器鎖

執行緒在進入同步程式碼塊之前會自動獲取鎖,並且在退出同步程式碼塊時自動釋放鎖,而無論是通過正常的控制路徑退出,還是通過從程式碼中丟擲異常退出,獲得內建鎖的唯一途徑就是進入由這個鎖保護的同步程式碼塊或方法

Java內建鎖相當於一種互斥體,最多隻有一個執行緒持有這種鎖。當執行緒A嘗試獲取執行緒B持有的鎖時,執行緒A必須等待或阻塞,直到執行緒B釋放這個鎖

5-什麼是重入?

如果一個執行緒試圖獲取一個已經由它自己持有的鎖,那麼這個請求就能成功!重入意味著獲取鎖的粒度是執行緒,而不是呼叫

JVM為每一個鎖關聯一個獲取計數值和一個所有者執行緒,當計數值為0時,這個鎖就被認為是沒有被任何執行緒持有,當執行緒請求一個未被持有的鎖時,JVM將記下鎖的持有者,並且將獲取計數值置為1,如果同一個執行緒再次獲取這個鎖,計數值遞增,而當退出同步程式碼塊時,計數器會相應的遞減,當計數值為0時,這個鎖將被釋放

當在無狀態的類中新增一個狀態時,如果該狀態完全由執行緒安全的物件來管理,那麼這個類仍然是執行緒安全的

要保持狀態的一致性,就需要在單個原子操作中更新所有相關的狀態變數

當執行時間較長的計算或者可能無法快速完成的操作時(例如,網路IO或者控制檯IO),一定不要持有鎖