簡體   English   中英

在JAVA中的線程之間共享變量

[英]Sharing variable between threads in JAVA

我有兩個線程對一個公共變量“ n”進行計算,一個線程每次增加“ n”,另一個線程每次減少“ n”,當我不在此變量上使用volatile關鍵字時,我無法理解的事情發生了,請幫忙解釋一下,代碼段如下:

public class TwoThreads {

private static int n = 0;
private static int called = 0;

public static void main(String[] args) {

    for (int i = 0; i < 1000; i++) {
        n = 0;
        called = 0;

        TwoThreads two = new TwoThreads();
        Inc inc = two.new Inc();
        Dec dec = two.new Dec();
        Thread t = new Thread(inc);
        t.start();
        t = new Thread(dec);
        t.start();
        while (called != 2) {
            //System.out.println("----");
        }
        System.out.println(n);

    }
}

private synchronized void inc() {
    n++;
    called++;
}

private synchronized void dec() {
    n--;
    called++;
}

class Inc implements Runnable {
    @Override
    public void run() {
        inc();
    }
}

class Dec implements Runnable {
    @Override
    public void run() {
        dec();
    }
}

}

1)我期望執行后為“ n = 0,稱為= 2”,但是主線程可能會在while循環中被阻塞;

2)但是當我取消注釋該行時,程序按預期進行:

//System.out.println("----");

3)我知道我應該在“被叫”上使用“易失性”,但是我無法解釋為什么會發生上述情況;

4)“被調用”是特定線程工作存儲器中的“讀取和加載”,但是為什么在“ long” while循環之后不將其“存儲並寫入”主線程,如果不是,為什么簡單的“打印”行可以有所作為

您已同步寫入數據(以inc和dec為單位),但尚未讀取數據(以main為主)。 兩者都應同步以獲得可預期的效果。 否則,main可能永遠不會“看到” inc和dec所做的更改。

您不知道確切執行被調用的++的位置,您的主線程將繼續產生新的線程,這將導致相互排斥,我的意思是每次只能有一個線程可以執行被調用的++,因為方法是同步的,並且您不知道每個線程確切的線程將是它。 在主線程達到您的條件時,可能執行兩次n ++或n--,您可能不知道,可能執行十次n ++。

並嘗試閱讀有關數據競賽的信息

 while (called != 2) {
            //System.out.println("----");
 }

//.. place for data race, n can be changed

 System.out.println(n);

你需要同步訪問called這里:

while (called != 2) {
    //System.out.println("----");
}

我建議添加getCalled方法

private synchronized int getCalled() {
    return called;
}

並用getCalled() != 2替換called != 2 getCalled() != 2

如果您對為什么會發生此問題感興趣,可以閱讀有關Java內存模型上下文中的可見性的信息。

暫無
暫無

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

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