2012-01-19 59 views
1

在下面的假設情景中,出於對更好理解語言的渴望,是否需要對int []進行參考?在這裏是不穩定的嗎?

public final class SO { 

    private int[] ar = new int[10]; // is volatile needed here? 
    private int idx = 0; 

    public synchronized int get(int i) { 
     return ar[i]; 
    } 

    public synchronized void append(final int val) { 
     if (idx == ar.length) { 
      // array is too small, let's grow it 
      final int[] prev = ar; 
      ar = new int[ar.length+ar.length*20/100] 
      System.arrayCopy(prev, 0, ar, 0, prev.length); 
     } 
     ar[idx++] = val; 
    } 

} 

到檢索的INT的唯一方法是槽一個同步方法和修改INT [](包括創建新INT [])的唯一途徑也做槽同步方法。

我不需要添加任何額外的同步權嗎?

+0

您已將此標記爲原始類型,但實際上int []是Object,因爲它是一個java數組。 – wmorrison365

+0

使'ar'易失性只對'ar'(而不是其中的元素)賦值一個易失性寫 –

+0

'ar.length + ar.length * 20/100' ='ar.length * 6/5' –

回答

3

不,volatile不需要,因爲它只能在synchornised方法內訪問,所以它已經是線程安全的。代碼中不需要進一步的線程安全。

2

它會像你說的那樣,因爲int受到類鎖的保護 - 但由於寫入和讀取訪問彼此阻塞,所以它會很慢。 (請參閱CopyOnWriteList實現以獲得更快的方式)

+0

我不知道「class lock」是否是公認的術語,但是它表明所有實例都有一個鎖。這與「synchronized(this){...}」塊等價。 – weston

+1

我認爲使用@GuardedBy(「this」)註釋該屬性以使其更加清晰更常見。所以它更像是一個類對象級別的聲明,而不是您交給對象鎖定的對象級別。 –

1

您很好,除非您的值在其他地方沒有同步訪問。

順便說一下,如果您確實製作了arvolatile而不是使用同步方法,則您還需要使idx變得非常不穩定。但是這仍然不足以實現同步,因爲同時運行兩個不同的線程會造成嚴重破壞。

實際上,使用volatile數組存在另一個問題:更改數組中的值不會觸發緩存同步。只重新分配數組(就像創建更大數組時一樣)會觸發緩存刷新。

1

作爲每 java lang specfication 具有揮發性添加嚴格的規則對線程(讀取來自主存儲器/寫),使用在該點點同步鬆弛。