Java線程安全問題指的是全局變量?
這個問題的答案是靜態變量和全局變量都可能引起線程安全問題。這兩種變量引起線程安全問題的原因和區別如下:
1、靜態變量
靜態變量即靜態成員變量。只要有修改變量值的操作,無論是在單例或者非單例都是線程不安全的;而如果線程只是讀取變量的值,而不會改變變量的值,這種情況下則是線程是安全的。
產生線程安全問題的原因:靜態變量即類變量,只初始化一次,位于方法區,為所有對象共享,共享一份內存,一旦靜態變量被修改,其他對象均對修改可見,故線程非安全。
靜態變量多線程操作示例:
根據上圖代碼可知,當線程1執行了number = 1; number = 2; 后,線程2獲得執行權,number = 1;然后當線程1獲得執行權執行打印第二次獲取number時; 必然輸出結果“獲取第二次number = 1”,按照這個模擬,我們可能會在控制臺看到輸出為“獲取第二次number = 1”的結果。如下圖方框中的數據:
上圖結果顯示了靜態變量線程不安全問題。
2、全局變量
全局變量即實例成員變量。如果線程只是讀取變量的值,而不會改變變量的值,則無論是單例還是非單例都是線程安全的;如果有修改變量值的操作,則單例模式因為只有一個對象實例singleton存在,多線程同時操作時是不安全的,而非單例模式下多線程操作是安全的。
實例變量為對象實例私有,在虛擬機的堆heap中分配,若在系統中只存在一個此對象的實例,在多線程環境下,“猶如”靜態變量那樣,被某個線程修改后,其他線程對修改均可見,故線程非安全(如,springmvc controller是單例的,非線程安全的);如果每個線程執行都是在不同的對象中,那對象與對象之間的實例變量的修改將互不影響,故線程安全(如,struts2 action默認是非單例的,每次請求在heap中new新的action實例,故struts2 action可以用實例成員變量)。
全局變量多線程操作示例:
多線程操作同一個對象的全局變量,結果如下圖:
上圖結果顯示了全局變量線程不安全問題。