回复
Java中的volatile关键字最全总结(四)
pivoteic
发布于 2022-6-15 17:05
浏览
0收藏
volatile的应用场景
由于volatile的特性,使得它适用于一些纯赋值的场景,对于一些非原子性的操作,比如:i++,volatile就不适合了,看一个例子:
public class VolatileDemo {
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
Thread t1 = new Thread(myThread);
Thread t2 = new Thread(myThread);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(myThread.flag);
System.out.println(myThread.atomicInteger);
}
}
class MyThread implements Runnable {
public volatile boolean flag = false;
public AtomicInteger atomicInteger = new AtomicInteger(0);
@Override
public void run() {
for (int i = 0; i < 5000; i++) {
change();
atomicInteger.incrementAndGet();
}
}
private void change() {
flag = true;
}
}
对于这个程序,输出的flag结果永远只能是true,但是如果将 flag = true 修改为 flag = !flag ,这就不是一个原子性的操作了,此时程序就会出现true或false的两种输出结果。
volatile还可用于变量的触发器,前面我们了解过happens-before原则,当某个volatile修饰的变量被赋值后,其它线程在获取该变量时,该变量及其之前的操作对其它线程均是可见的,例如:
public class VolatileDemo {
private int a = 1;
private int b = 2;
private int c = 3;
private volatile boolean flag = false;
private void write() {
a = 3;
b = 4;
c = 5;
flag = true;
}
private void read() {
while (flag) {
System.out.println("a=" + a + ",b=" + b + ",c=" + c);
}
}
public static void main(String[] args) throws InterruptedException {
VolatileDemo volatileDemo = new VolatileDemo();
while (true) {
new Thread(() -> {
volatileDemo.write();
}).start();
new Thread(() -> {
volatileDemo.read();
}).start();
}
}
}
在read()方法中,当flag值为true时会输出变量a、b、c的值,而如果flag为true的话,那么为flag赋值之前的操作都将是可见的,所以变量a、b、c的值一定分别是3、4、5,这就相当于一个触发器,当触发器变量满足条件时,刷新之前的变量得到最新值,触发器典型的应用场景就是Web容器的初始化。
本文作者:汪伟俊 为Java技术迷专栏作者 投稿,未经允许请勿转载
文章转自公众号:三友的java日记
标签
已于2022-6-15 17:05:19修改
赞
收藏
回复
相关推荐