簡體   English   中英

為什么用兩個易變變量進行重新排序?

[英]Why reordering takes place with two volatile variables?

我正在嘗試調查Java環境中的重新排序行為(使用JDK 9-ea + 170),發現有一件我自己無法解釋的事情,因此,我將很高興聽到一些有關它的注釋。 這是一個例子:

public class Client {
    int x;
    int y;
    public void test() {
        x++;
        y++;
    }
    public static void main(String[] args) {
        Client c = new Client();
        while(c.y <= c.x) new Thread(() -> c.test()).start();
        System.out.println(c.x + " " + c.y);
    }
}

該程序具有一個test()方法,該方法僅遞增x和y值。 我正在創建新的線程並調用此test()直到某些內部Java優化未更改x++; y++;的順序x++; y++; x++; y++; 說明()。 這樣,我證明重新排序確實發生了。 並且程序在大多數時間結束(這是預期的)。 現在,我向y添加了volatile修飾符:

public class Client {
    int x;
    volatile int y;
    public void test() {
        x++;
        y++;
    }
    public static void main(String[] args) {
        Client c = new Client();
        while(c.y <= c.x) new Thread(() -> c.test()).start();
        System.out.println(c.x + " " + c.y);
    }
}

該程序永遠不會結束,因為volatile保證volatile之前的所有指令都將被刷新到內存中,因此x++; 總是在y++;之前執行y++; 並且不可能使y> x。 根據我的理解,這也是可以預期的。 但是之后,我在int x;添加了volatile int x; 我現在也可以再次看到重新排序,所以程序大多數時間結束:

public class Client {
    volatile int x;
    volatile int y;
    public void test() {
        x++;
        y++;
    }
    public static void main(String[] args) {
        Client c = new Client();
        while(c.y <= c.x) new Thread(() -> c.test()).start();
        System.out.println(c.x + " " + c.y);
    }
}

為什么還要在這里進行重新排序?

這不是重新排序的證據。 實際上,發生的事情是由於volatile上的++不是原子的。 例如,在更新變量( x )之一時,請考慮以下兩個線程( AB )對操作的交織:

thread A: load x -> temp
thread B: load x -> temp
thread A: temp = temp + 1
thread B: temp = temp + 1
thread A: save temp -> x
thread B: save temp -> x

並且如果您通過這種交錯處理這些操作,您會發現您對x失去了計數。 這足以使cy <= cx偶爾失敗。

y也會發生“計數丟失”行為,這解釋了為什么該實驗有時會失敗。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM