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