新闻资讯

新闻资讯 通知公告

JAVA:Volatile关键字失效

编辑:009     时间:2020-03-02

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);
    }
}

输出结果:

————————————————
版权声明:本文为CSDN博主「Crzis」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ling_du/article/details/98510821

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

回复列表

相关推荐