【線程不安全問題】

1.消失的請求數
         當我們要計算一個類中的某個函數被調用的次數時,用單線程跑絕對沒問題,但是放到多線程中就會出事。
         因爲 count ++ 的操作過程是:讀取->修改->寫入
         假設線程A和線程B同時調用了函數,那麼他們讀取count的值是一樣的,接着增加數值,最後兩個線程寫入的數值都是一樣的,造成少增加一次的錯誤。

2.構造出兩份相同的對象
         構造函數私有化,我們會寫一個公用返回參數爲對象的函數,用於返回一個new出來的對象。
         當兩個線程同時調用這個函數時,就會產生返回兩個相同的對象,即兩個地方公用一個對象的錯誤。

 

3.對象逸出
         在一個構造函數中:1)接收一個事件源,添加一個監聽器,任務是觸發時,就操作this屬性。2)對屬性的初始化(new)
         當線程A調用構造函數,還未對屬性進行初始化時,線程B恰好也調用了構造函數,觸發了事件源,由於線程A已經往事件源註冊了監聽器,因此線程B會觸發任務,操作this的屬性
         此時的this屬性還未初始化,會報空指針異常。

 

4.半成品
         對象逸出是指不想發佈對象,卻不小心發佈了。想發佈對象,卻在對象還沒製造好之前,就給了對方使用半成品的機會。

 

這四個例子,分別對應三種常見的線程不安全情形:

  • 讀取-修改-寫入: 對應上面“消失的請求數”的例子
  • 先檢查後執行:對應上面“意外懷孕”的例子
  • 發佈未完整構造的對象:對應上面“考題泄漏”和“半成品”兩個例子

絕大多數的線程不安全問題,都可以歸結爲這三種情形。而這三種情形,其實又可以再縮減爲兩種:對象創建時和對象創建後。不僅僅是在對象創建後的業務邏輯中要考慮線程的安全性,在對象創建的過程中,也要考慮線程安全。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章