Volatile關鍵字失效

volatile關鍵字用於修飾簡單類型變量,如int、float、boolean等數據類型,保證同一時刻只能有一個線程修改變量。

volatile修飾變量的操作就會變成原子級別的,但這有一定的情況時效:

public class VolatileTEST {

    volatile static int val = 0;

    public static void  main(String[] args) throws InterruptedException{
        Thread t1 = new Thread(() -> {
            for(int i=0; i<300000; i++){
                val += 1;
            }
        });
        Thread t2 = new Thread(() -> {
            for(int i = 0; i<300000; i++){
                val += 1;
            }
        });
        long startTime =  System.currentTimeMillis();
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println("時間:" + (System.currentTimeMillis() - startTime) + "毫秒");
        System.out.println(val);
    }
}

這個實例期望的是得到600000,但是實際運行結果:

 

原因是:val +=1 並不是原子操作。 當volatile修飾簡單變量,當前值是根據以前的值得到時,例如:val+=1,val=val+1 , val++等,volatile關鍵字將失效。只有當變量的值和以前的值無關時,對該變量的操作纔是原子級別,如val = n + 1。

      這時候需要使用synchronized把操作(例如val+=1)抽取成一個方法:

public class VolatileTest2 {
    static int val = 0;

    public static synchronized void inc(){
        val += 1;
    }

    public static void  main(String[] args) throws InterruptedException{
        Thread t1 = new Thread(() -> {
            for(int i=0; i<300000; i++){
                inc();
            }
        });
        Thread t2 = new Thread(() -> {
            for(int i = 0; i<300000; i++){
                inc();
            }
        });
        long startTime =  System.currentTimeMillis();
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println("時間:" + (System.currentTimeMillis() - startTime) + "毫秒");
        System.out.println(val);
    }
}

輸出結果:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章