簡體   English   中英

java中的volatile vs threadLocal

[英]volatile vs threadLocal in java

讓我們以SimpleDateFormat為例,因為它不是線程安全的。

我可以允許每個線程使用threadLocal擁有自己的SimpleDateFormat副本,如下所示:

 private static final ThreadLocal<SimpleDateFormat> formatter = new ThreadLocal<SimpleDateFormat>(){
    @Override
    protected SimpleDateFormat initialValue()
    {
        return new SimpleDateFormat("yyyyMMdd HHmm");
    }
};

但volatile關鍵字保證線程將擁有該變量的最新副本。 所以我不能這樣做:

volatile SimpleDateFormat myformatter;

並實現相同的線程安全?

volatile關鍵字保證線程將擁有該變量的最新副本

只有 volatile變量,而不是它的字段。

此外, volatile僅在您需要更改變量值時才有用。 在您的用例中, final看起來更合適:

private static final SimpleDateFormat format = ...

這也保證了你將獲得變量的最新值 - 因為它只能被賦值一次,而static final在類完全加載后保證了可見性。


但這並不是SimpleDateFormat無論如何都不是線程安全的原因:它具有可變狀態,用於在格式化日期時存儲中間值。

如果一個線程調用format而另一個線程也在同一個SimpleDateFormatter實例的format方法中,則這些中間變量會不可預測地被踩踏,從而導致線程之間的干擾,從而導致不可預測的輸出。

在由另一個線程讀取/寫入時,這些中間變量的值是否是最新的並不重要 - 它們的更新可以散布。

簡而言之, volatile不會阻止線程干擾,因此這里不是ThreadLocal的合適替代品。

ThreadLocal是一種工具,它使線程擁有自己的對象本地副本。 ThreadLocals最適用於在線程限制的線程安全策略中可以線程安全的對象(即使對於許多不是“線程安全”的對象,只要沒有對它們的引用從限制中泄漏,線程安全使用仍然是可能的線)。 ThreadLocals無法幫助在實例化它們的線程之外共享的可變對象的線程安全使用。

volatile關鍵字用於通過可由許多不同線程訪問的變量提供弱形式的線程安全性。 一個關鍵的區別是ThreadLocals通常不被多個線程訪問。

從廣義上講,線程安全需要可見性(變量的最新更新應該對其他線程可見)和互斥(狀態轉換必須是原子的,以便不能觀察到狀態不一致)。 Volatile與Java Memory Model一起使用以保證變量可見,但它不提供任何形式的互斥,因此不會為對象中的狀態轉換提供原子性。

因為volatileThreadLocal是如此不同,所以實際上沒有一個常見的情況可以用一個代替另一個。

您沒有使用volatile實現相同的線程安全volatile因為SimpleDateFormat相同實例將在不同的線程中使用。

暫無
暫無

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

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