2015-12-27 36 views
3

我有多個線程訪問class Aufzahlen並遞增cc變量。我不知道我是不是把cc放在volatile上,但是我的synchronized方法在這裏有任何錯誤的空間嗎?由於cc變量一次只能訪問一次。如果方法同步需要揮發性?

線程是否仍有可能在自己的緩存中存在cc變量並因此而導致混亂?我一直在運行這個代碼示例一段時間,到目前爲止沒有發現任何錯誤。

public class Aufzahlen { 
private int cc=1; 

    public synchronized void aufzahlen() throws InterruptedException { 
    cc = cc +1; 
    } 


    public synchronized void printa() { 
    // TODO Auto-generated method stub 
    System.out.println("Thread: " + Thread.currentThread() + "Zahl: " + cc); 
    } 

{ 
+0

如果您正確地將所有其他訪問同步到'cc',則不會,變量不需要是易失性的。因爲cc變量是無用的,因爲沒有人讀過它。不知道爲什麼你有'拋出InterruptedException'。另外,你可以使用'cC++'。 –

+0

我編輯了一個方法來讀取變量 –

+0

cc的同步訪問是可以的。正如JB已經提到的那樣。如果只處理cc,也可以使用AtomicInteger。 – Dwijendra

回答

4

1.可見性

該方法不會失敗。如果你每次同步你訪問一個字段,它的變化是保證每一個線程持有相同的鎖定時間是可見的,如下面所示:

enter image description here

從Java併發實踐[pdf]圖3.1

因此,使字段不穩定是不必要的。通過使用AtomicIntegergetAndIncrement()incrementAndGet()方法,您可能會更好,它可以達到相同的目的,但具有更好的併發吞吐量(它們使用原生功能而不是鎖定,它們專門用於完成此任務) - 但要確保AtomicInteger本身的內存可見性給出(最簡單的方法是使它最終 - 它不會使AtomicInteger的值最終)。

public class Aufzahlen { 
    private final AtomicInteger atomicInt = new AtomicInteger(1); // set initial value with constructor argument 

    public void aufzahlen() { 
     atomicInt.incrementAndGet(); 
    } // no need for synchronization because updates are atomic and are automatically visible 
} 

2.原子性

我可能在這篇文章已經使用「原子」一次或兩次,則意味着沒有兩個線程可併發執行相同的代碼,或者,換句話說,該操作不能被「分割」成多個線程可能同時在內部的多個部分。

+--- Function aufzählen() without synchronization and with i++ ---------------+ 
|                    | 
| [Get i from field] --> [Increment i locally] --> [Write new value to field] | 
|     ^      ^       | 
|      |       |        | 
|   "Race condition", multiple threads could be at these stages  | 
|   -> operation not atomic           | 
+-----------------------------------------------------------------------------+ 

我只是demonstated什麼也不是原子的,可以讓這個操作使用​​原子(下一個線程需要等待第一個完成整個方法),或者你可以使用AtomicInteger這確實原子性的您。

0

volatile變量告訴編譯器在寄存器中從來沒有在緩存讀取和寫入操作的價值。 CPU高速緩存(L1,L2等)仍然使用。

如果所有對此變量(在類的單個實例中)的訪問都來自多個線程,則它們都應受到保護。

如果你有興趣從另一個線程讀取這個cc值沒有同步,那麼是的,使它volatile。這將有效地使同步成爲寫鎖。

+0

這種說法是正確的嗎? 一個簡單的答案如下: 同步總是可以被用來給你一個線程安全/正確的解決方案, 波動可能會更快,但只能用來給你一個線程安全/糾正有限的情況。 –

0

由於同步塊,源代碼沒有問題。字段cc將僅被同時訪問一個線程,因爲兩個不同的線程將不被允許同時執行同步塊。