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