本文介紹了Java并行易失性I++的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!
問題描述
我有一個全局變量
volatile i = 0;
和兩個線程。每個組件執行以下操作:
i++;
System.out.print(i);
我收到以下組合。12、21和22。
我理解為什么我不能得到11(易失性不允許緩存I)和我也理解12和22。
我不明白的是,怎么可能得到21?
獲得這種組合的唯一可能方法是,稍后打印的線程必須是第一個將i
從0遞增到1,然后緩存i==1
。然后另一個線程將i
從1遞增到2,然后打印2。然后第一個線程打印緩存的i==1
。但我認為volatile
不允許緩存。
編輯:在運行代碼10,000次之后,我得到了11次。將volatile
添加到i
根本不會更改可能的組合。
markspace是對的:Volatile禁止i
緩存,但i++
不是原子的。這意味著i
在遞增期間仍會在寄存器中得到某種程度上的”緩存”。
r1 = i
//if i changes here r1 does not change
r1 = r1 + 1
i = r1
這就是11仍然有可能的原因。21是因為PrintStream未同步(請參閱Karol Dowbecki的答案)
推薦答案
不幸的是++
不是原子操作。盡管volatile
不允許緩存,但允許JVM作為單獨的操作進行讀取、遞增和寫入。因此,你試圖實現的概念是行不通的。您需要使用synchronized
作為其互斥鎖,或者使用類似于AtomicInteger
的命令來提供原子增量操作。
這篇關于Java并行易失性I++的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,