volatile做信号量的疑问

来源:3-4 线程安全性-可见性

磊磊要酷酷滴

2019-03-27

  • 信号量不用volatile修饰不也可以吗?
  • 我写了个信号量的demo如下,去掉volatile也完全可以啊?
public class VolatileDemo1 {

    public static volatile boolean inited = false;
    public static int var = 0;

    public static void main(String[] args) {
        ExecutorService service = Executors.newCachedThreadPool();

        service.execute(() -> {
            try {
                TimeUnit.MILLISECONDS.sleep(2);
                var = -1;
                inited = true;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        service.execute(() -> {
            while (!inited) {
                System.out.println(var++);
            }
            System.out.println(var);
        });

        service.shutdown();
    }

}
写回答

1回答

Jimin

2019-03-27

你好,信号量里使用volatile主要是利用他的可见性。使用了volatile后,可以保证每次读都是内存里最新的值,这样可以保证做到,只要volatile修饰的变量发生了变化,那么下次循环就一定能按照变化后的值进行操作。放过来讲,没有volatile修饰,那么由于不具备可见性,某个线程里修改了共享变量,其他线程是不确定什么时候能过来读取到最新的值的。但是,这不代表其他线程永远读取不到最新的值。

因此,去掉volatile不代表一定会永远读取不到最新的值,这个可以类比线程不安全问题,有些代码尽管有线程不安全的风险,但这不代表一定会触发线程不安全。从实际角度出发,做为一个信号量,我们预期的肯定是只要这个信号发生变化,其他使用这个信号的地方都能立即感知到。

1
1
磊磊要酷酷滴
翻阅了老师提到的《深入理解Java虚拟机 第2版》中关于volatile的讲述,此处加volatile修饰,还能禁止指令重排的问题,避免在最后一行对信号量的修改操作提前到前面运行;加上老师解释的,volatile让信号量在修改后,对其他线程立马可见,对volatile的理解更深刻了;谢谢老师的耐心讲解^_^
2019-03-29
共1条回复

Java高并发编程,构建并发知识体系,提升面试成功率

构建完整并发与高并发知识体系,倍增高薪面试成功率!

3923 学习 · 832 问题

查看课程