簡體   English   中英

如何在Java中正確使用volatile

[英]How to use volatile correctly in Java

我正在研究Java Thread,當我分析從例8.3.1.4修改的以下代碼時,關鍵字volatile會讓我感到困惑

public class Volatile {
    public static void main(String[] args){
        MyRunnable1 myRunnable1 = new MyRunnable1();
        MyRunnable2 myRunnable2 = new MyRunnable2();
        Thread t1 = new Thread(myRunnable1);
        Thread t2 = new Thread(myRunnable2);

        t1.start();
        t2.start();
    }
}

class MyRunnable1 implements Runnable{
    public void run(){
        while(true){
            Test1.one();
        }
    }
}
class MyRunnable2 implements Runnable{
    public void run(){
        while(true){
            Test1.two();
        }
    }
}

class Test1{
    static volatile int i = 0;
    static volatile int j = 0;
    static void one(){
        i ++;
        j ++;
    }

    static void two(){
        System.out.println("i = " + i  + " j = " + j);
    }
}

輸出段:

i = 60778110 j = 60778116
i = 60778402 j = 60778407
i = 60778630 j = 60778636
i = 60779062 j = 60779079
i = 60779492 j = 60779497
i = 60779784 j = 60779789
i = 60780161 j = 60780169
i = 60780625 j = 60780632
i = 60780936 j = 60780942

我的想法是,由於volatilei ++發生在j ++之前,它們的初始值為零,修改后的值將立即刷新到主存儲器,因此i線程t2看到的任何時候都應該大於j 但是輸出顯示i總是低於j

然后我修改這two函數如下:

static void two(){
    System.out.println("j = " + j  + " i = " + i);
}

的變化是, j輸出之前i ,然后輸出段如下:

j = 47324409 i = 47324412
j = 47324587 i = 47324593
j = 47324808 i = 47324813
j = 47324991 i = 47324996
j = 47325193 i = 47325196
j = 47325347 i = 47325353

令我驚訝的是, j總是低於i

我的想法是j是較低的,因為它首先被連接,並且在i連接一段時間之后,在時間間隔期間, one函數執行導致i增加。

所以第一個連接值將低於第二個連接值,是不是? 提前致謝!

你猜對了。 不同之處在於println調用的參數分為3個步驟:

  1. 構建字符串s =“i =”+ i
  2. 構建字符串s = s +“j =”
  3. 構建字符串s = s + j

在Runnable2執行此操作時,特別是在step1之后和最終打印之前,Runnable2正忙於遞增值。 這會導致你看到的行為。

這不是揮發性的問題。 如果希望i和j同步,則必須同步Test1類的方法。

實際上, volatile只是阻止線程緩存一個值,而是強制“直寫”和“讀取”:如果一個線程緩存一個變量並由另一個線程更新,那么第一個線程的值可能永遠不會改變,因為Java的緩存策略,不需要刷新其緩存。

因此,每當您有多個線程訪問和更改原始資源(如int,boolean或引用類型引用值本身)時,您應該使用volatile。

這本身並不意味着volatile實際上使變量訪問線程安全!

暫無
暫無

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

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