volatile 可見性與原子性

Wayne_Kdl發表於2019-12-05

git地址:github.com/fw103699437…

不具有原子性

public class NotAtomicDemo {
    volatile static int k;
//    static int k = 0;
    public static void main(String[] args) {
        int num = 100000;
        CountDownLatch countDownLatch = new CountDownLatch(num);
        for (int i = 0; i < num; i++) {
            new Thread(()->{
                k++;
                countDownLatch.countDown();
            }).start();
        }


        try {
            countDownLatch.await();
            System.out.println(k);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
複製程式碼
99994
顯然volatile不具有原子性,這個不用多說
Process finished with exit code 0
複製程式碼

具有可見性

public class VisibilityDemo {
    static int k = 0;
//    volatile static int k = 0;

    public static void main(String[] args) {
        new Thread(()->{
            while (true){
                if(k>=5){
                    System.out.println("______________k可見了" + new Date(System.currentTimeMillis()) +"           " +  k);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

        new Thread(()->{
            while(true){
                k++;
                System.out.println("k++" + new Date(System.currentTimeMillis()) + "    " + k);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}
複製程式碼
k++Thu Dec 05 18:12:34 CST 2019    1
k++Thu Dec 05 18:12:35 CST 2019    2
k++Thu Dec 05 18:12:36 CST 2019    3
k++Thu Dec 05 18:12:37 CST 2019    4
k++Thu Dec 05 18:12:38 CST 2019    5
k++Thu Dec 05 18:12:39 CST 2019    6
k++Thu Dec 05 18:12:40 CST 2019    7
k++Thu Dec 05 18:12:41 CST 2019    8
k++Thu Dec 05 18:12:42 CST 2019    9
k++Thu Dec 05 18:12:43 CST 2019    10
複製程式碼

說明第一個執行緒沒有意識到k已經>=5了,而且過了很久都沒有意識到,多次實驗均如此,

加上volatile之後

//    static int k = 0;
    volatile static int k = 0;
複製程式碼
k++Thu Dec 05 18:15:07 CST 2019    1
k++Thu Dec 05 18:15:08 CST 2019    2
k++Thu Dec 05 18:15:09 CST 2019    3
k++Thu Dec 05 18:15:10 CST 2019    4
k++Thu Dec 05 18:15:11 CST 2019    5
______________k可見了Thu Dec 05 18:15:11 CST 2019           5
______________k可見了Thu Dec 05 18:15:12 CST 2019           6
k++Thu Dec 05 18:15:12 CST 2019    6
______________k可見了Thu Dec 05 18:15:13 CST 2019           7
k++Thu Dec 05 18:15:13 CST 2019    7
複製程式碼

第一個執行緒可以意識到k>5了,多次試驗均是如此。

還有一些沒想明白的問題

            while (true){
                //加上之後k居然可見了
                System.out.println("sout");
                if(k>=5){
複製程式碼

在while和if之間加上一句之後,在五秒後,第一個執行緒就可以看到k更新了,,多次實驗均如此

                if(k>=5){
                    System.out.println("______________k可見了" + new Date(System.currentTimeMillis()) +"           " +  k);
                    //拿到if外 也可見

                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
複製程式碼

或者把sleep放到if外,五秒後,第一個執行緒也可以看到k更新,多次實驗均如此

這就有點想不通了。

結論

雖然有想不通的地方,不過在原子性,可見性上還是有一些收穫的,volatile可以立即看到新的值(可見性),但是不具有原子性。

相關文章