1

below code listings中,語句1和語句2是否安全?他們正在使用VolatileIntWrapper在多線程應用程序中使用帶易失性基元的條件運算符是安全的

如果它們不是線程安全的,哪些語句需要包裝在同步塊中?

public class Demo { 

    public static void main(String[] args) { 

     VolatileIntWrapper volatileIntWrapper = new VolatileIntWrapper() ; 

     for(int i = 1 ; i <= 5 ; ++i){ 
      new ModifyWrapperIntValue(volatileIntWrapper).start() ; 
     } 
    } 
} 

class VolatileIntWrapper{ 
    public volatile int value = 0 ; 
} 

class ModifyWrapperIntValue extends Thread{ 

    private VolatileIntWrapper wrapper ; 
    private int counter = 0 ; 

    public ModifyWrapperIntValue(VolatileIntWrapper viw) { 
     this.wrapper = viw ; 
    } 

    @Override 
    public void run() { 

     //randomly increments or decrements VolatileIntWrapper primitive int value 

     //we can use below statement also, if value in VolatileIntWrapper is private 
     // wrapper.getValue() instead of wrapper.value 
     //but, as per my understanding, it will add more complexity to logic(might be requires additional synchronized statements), 
     //so, for simplicity, we declared it public 


     //Statement 1 
     while(wrapper.value > -1500 && wrapper.value < 1500){ 
      ++counter ; 
      int randomValue = (int) (Math.random() * 2) ; 

      //Statement 2 
      wrapper.value += (randomValue == 0) ? 1  :  -1 ; 
     } 

     System.out.println("Executed " + counter + " times..."); 
    } 
} 

回答

4

volatile keyword爲閱讀和寫字段提供了內存屏障。這意味着多個線程可以訪問該字段並保證讀取最新的值,並保證它們的寫入被其他線程看到。

什麼volatile確實不是 do是圍繞操作順序提供任何保證 - 尤其是當您有多個讀寫語句時。在你的代碼正在訪問在循環中volatile int幾個地方:

while(wrapper.value > -1500 && wrapper.value < 1500){ 
     ... 
     wrapper.value += (randomValue == 0) ? 1  :  -1 ; 
    } 

有沒有保證,而這裏的操作順序。線程A立即測試value > -1500後,另一個線程可能會在之前更改它線程A可以測試value < 1500。或者線程A可以執行兩個測試,然後線程B可以執行兩個測試,然後線程A將分配該值,然後線程B將分配該值。這是multithreading race conditions的性質。

while循環是我懷疑會被視爲有一個錯誤的代碼段,除非你圍繞它進行同步。你應該做下面的事情。一旦同步該部分,​​關鍵字本身就提供了內存屏障,因此volatile關鍵字是不必要的。

synchronized (wrapper) { 
     while (...) { 
     ... 
     } 
    } 
+0

它示出了定義:'類VolatileIntWrapper { 公共揮發性int值= 0; }' – GingerHead 2012-07-13 05:58:01

+0

謝謝@Mike。忽略了。 – Gray 2012-07-13 05:59:40

+0

@格雷:感謝這個詳細而又好的解釋......接受。 – mogli 2012-07-13 06:49:08

2

一次且只能使用一次volatile字段是安全的。 (讀取和寫入的次數爲兩次)

您使用的字段總共四次,因此您有三個競爭條件的地方。

這個例子的問題是單線程執行速度更快,更簡單,所以你用多線程方式做的任何事情都會顯得不自然和低效。

0

的問題需要解釋如下:

您正在使用的線程是安全的,你正在閱讀的原始價值,因爲它意。

有一個特定術語使用同步的原始場塊,但你需要做到以下幾點:

  • 使用getter和所在領域的制定者。
  • 把同步在兩個訪問器和瞧。
0

Java In Concurrencty說以下條件需要滿足touse揮發性變量:

1. Writes to the variable do not depend on its current value, or you can ensure that only a single thread ever updates the value; 

2. The variable does not participate in invariants with other state variables; and 

3. Locking is not required for any other reason while the variable is being accessed. 
相關問題