簡體   English   中英

意外的線程行為。 能見度

[英]Unexpected thread behavior. Visibility

我有以下代碼:

public static boolean turn = true;

public static void main(String[] args) {
    Runnable r1 = new Runnable() {
        public void run() {
            while (true) {
                while (turn) {
                    System.out.print("a");
                    turn = false;
                }
            }
        }
    };
    Runnable r2 = new Runnable() {
        public void run() {
            while (true) {
                while (!turn) {
                    System.out.print("b");
                    turn = true;
                }
            }
        }
    };
    Thread t1 = new Thread(r1);
    Thread t2 = new Thread(r2);
    t1.start();
    t2.start();
}

在課堂上,我們了解了使用非同步代碼時可能發生的“可見性”問題。 我知道,為了節省時間,編譯器將為循環決定對CPU緩存的抓取turn ,這意味着線程不會知道RAM中的turn值是否已更改,因為他不檢查它。

據我了解,我希望代碼像這樣運行:

T1將看到轉為true->進入循環並打印->將轉為false->被卡住

T2會認為轉彎沒有改變->會被卡住

我希望如果T1在T2之前開始:只會打印'a',並且兩個線程都將在無限循環中運行而無需打印其他任何內容

但是,當我運行代碼時,有時我會在兩個線程卡住之前得到一些“ abab ....”。

我想念什么?

編輯:

以下代碼完成了我所期望的:線程將在無限循環中運行:

public class Test extends Thread {
boolean keepRunning = true;

public void run() {
    long count = 0;
    while (keepRunning) {
        count++;
    }
    System.out.println("Thread terminated." + count);
}

public static void main(String[] args) throws InterruptedException {
    Test t = new Test();
    t.start();
    Thread.sleep(1000);
    t.keepRunning = false;
    System.out.println("keepRunning set to false.");
}

}

它們彼此之間有何不同?

當我運行代碼時,有時我會在兩個線程卡住之前得到一些“ abab ....”。

我懷疑正在發生的事情是,在對代碼進行JIT編譯時,行為正在改變。 在JIT編譯之前,寫操作是可見的,因為解釋器正在執行寫操作。 在JIT編譯之后,緩存刷新或讀取已被優化……因為內存模型允許這樣做。

我想念什么?

您缺少的是您期望未指定的行為是一致的。 不一定是。 畢竟,它是未指定的! (這是正確的,即使我上面提出的解釋不正確。)

turn不是不穩定的事實並不意味着您的代碼會中斷,而可能會中斷。 就我們所知,線程在任何給定時刻都可能看到false或true。 無需特別說明,就可以隨意清除緩存,線程可以保留其緩存等。

這可能是因為您的代碼正在遭受System.out.print副作用,該副作用在內部寫入同步方法:

  521       private void write(String s) {
  522           try {
  523               synchronized (this) {

資料來源-DocJar

同步的內存影響可能會刷新緩存,因此會影響您的代碼。

正如@Stephen C所說,它也可能是JIT,它可能會進行布爾檢查,因為它假定值不會由於另一個線程而改變。

因此,在到目前為止提到的三種不同的可能性中,它們都可能是影響代碼行為的因素。 可見性是一個因素,而不是決定因素。

暫無
暫無

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

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