簡體   English   中英

初始化的非最終靜態變量是線程安全的嗎?

[英]Is initialized non final static variables are thread safe?

假設,我有一個私有的非最終靜態變量,並在靜態塊中進行了初始化,並且在初始化后不會進行修改,也沒有修改該變量的方法。 它是線程安全的嗎?

class Test
{
     private static int value = 10;

     public static int getValue()
     {
        return value;
     }
 }

我只是想知道JVM為非最終靜態變量提供什么保證,而沒有任何方法可以從線程安全的角度修改變量,在這種情況下,多個線程會嘗試讀取數據。

初始化類的過程( JLS 11.4.2 )指出,初始化是在持有鎖的同時執行的。 我認為這意味着初始化完成后引用靜態變量的任何線程都將看到完全初始化的狀態。

如果遇到以下情況,您可能會遇到麻煩:一個類的靜態初始化創建並啟動了一個線程,該線程可以在另一個類的靜態變量完成靜態初始化之前觀察該變量。 在這種情況下,可能無法保證線程將看到初始化狀態。


另一個需要注意的是,這里我們只討論靜態變量中的值。 如果這些變量引用了可變對象或數組,並且這些對象/數組發生了突變,則您的代碼不是自動線程安全的。

這說明了一個更大的觀點。 您實際上不能孤立地談論變量的線程安全性。 公認的線程安全定義是,引入線程不會導致某些錯誤行為。 變量沒有行為。 行為是應用程序級別的事情,盡管有時考慮應用程序一部分的行為是有意義的。 例如特定應用程序上下文中的某些類或方法。


在兩行之間閱讀……您似乎在嘗試避免在使用靜態方法時出現同步的“開銷”。 一切都很好……但是,線程安全性,靜態初始化和內存模型都是Java語言中最難/最難理解的部分。 在實現“聰明”或“有效”的減少同步開銷的方法時,許多真正聰明的人(過去)曾嘗試過並失敗了。

我的建議:不要太聰明。 把事情簡單化。 同步開銷不夠大(IMO),冒着將“ heisenbugs”引入代碼庫的風險。

最后,公認的是,靜態變量,尤其是可變的靜態變量是不良的OO設計。 我建議您考慮修改設計以消除它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM