2012-12-06 79 views
1

以下類線程安全嗎?我很擔心併發讀取和寫入初始化變量。如果它不是線程安全的,如何使線程安全?這個java類線程安全嗎?併發讀寫

  1. 我知道轉換到了methodA將同步幫助,但我不希望這樣做
  2. 如何添加揮發性keywork爲「初始化」變量?
​​

UPDATE1: 初始化可變將只在init方法一旦被改性,所有其他方法將只准備。如果是這種情況,將volatile添加到初始化將使其線程安全,是否正確?

+0

該類絕對不是線程安全的,並且使您的'initialized'變量'volatile'不會使其線程安全。問題是,你能忍受嗎?如果你的程序在'initialized'爲'false'時確實拋出一個異常,並且什麼也沒有做,那麼在'initialized'變量'volatile''之後,答案可能是'是'。 – dasblinkenlight

+2

詢問這些方法是否因其使用而「安全」是沒有意義的。 –

+0

@dasblinkenlight,是的,methodA會拋出異常。如果初始化是不穩定的,我認爲它應該是線程安全的 – performanceuser

回答

3

不,它不是線程安全的。當調用methodA時,init例程可能在設置initialized的中間。由於methodA未同步,所以執行initialized = trueif(!initialized)中的讀取之間沒有任何阻礙。事實上,寫甚至可能發生,但根本還沒有傳播到所謂methodA

添加volatileinitialized將與價值傳播問題幫助線程,但不與第一。

欲瞭解更多信息,我建議Brian Goetz的文章Managing Volatility

+0

如果我添加volatile來初始化,爲什麼它不是線程安全的?你可以解釋嗎? – performanceuser

+0

@performanceuser - 如果'init()'用'initialized'做的所有事情都是在開始時測試它,然後在最後寫入它,那麼方法本身不需要同步,你可以通過' volatile'。 (如果'init()'本身可能是從多個線程中調用的,那麼它仍然需要同步)。在我分析的Goetz文章中,對這個分析的確切因素進行了很好的描述。 –

0

沒有它不是線程安全的。 你必須同步。

0

@HotLicks是100%正確的。任何關於併發性的問題都需要提供上下文。原因如下:

讓我們假設一個類已經寫成「安全」(忽略OPs類)。如果你在一個實例變量上進行同步,並且類的實例被許多線程共享,那麼它將是線程安全的。但是,如果可以通過不同的線程創建類的多個實例,並且它們可能會修改靜態變量/狀態,那麼如果您在靜態(即類)變量上進行同步,它將只會是線程安全的。

總結:

  1. 如果共享線程之間單個實例,然後在實例變量鎖定
  2. 如果線程創建的「安全」的類和靜態狀態的情況下,潛在地通過這些線程改性,那麼必須鎖定靜態(類)變量