关于volatile关键字,对比了《Java并发编程实战》和《深入理解Java虚拟机》,发现前者是忽悠,即使不是忽悠,也是不清不楚。后者才是真牛逼,还是国人写的,真是厉害啊。

我的结论就是:

1、共享可变的long、double变量如果没有锁保护,就要用volatile,防止某些虚拟机应用了“非原子性协定”。其他所有地方,可以按建议使用volatile,也可以不使用。

2、所谓的volatile“可见性”对于编程没有意义,虽然volatile变量在线程间同步快一些,但相应的减少了线程运算的性能。非volatile虽然同步慢一点,但是总会有的。

3、所谓的“禁止指令重排序优化”,仅对volatile变量生效,两个volatile变量,才会使执行时序遵守代码时序。要识别出哪些代码应该禁止优化,简直是一项比架构一个系统更加庞大的任务。所以直接java指定禁止重排序就好了,为了这点性能提高,不值。

喜闻乐见的如下代码:

private boolean goon = true;
// one thread
public void stop() {
    goon = false;
}
// another thread
public void run() {
    while (goon) {
        dosomething();
    }
}

不用volatile真的就不行了吗,会挂吗?显然不是的!

《深入理解Java虚拟机》和《Java并发编程实战》在这一点上面有矛盾,根据文章的逻辑性高低,我宁愿相信前者的理论。

《深入理解Java虚拟机》说,“禁止指令重排序优化”只能作用在volatile变量之间(参考12.3.3节,volatile特殊规则最后一段话),那么goon变量即使声明成volatile,也没有另一个volatile变量去和它配合适应这条规则啊,那这条规则在这里就没有用了。

根据这本书的说法推导,在这里把goon声明为volatile,作用就是可以省去缓存线程内存的步骤,类似于直接在主存上面进行变量读写。所以volatile变量的变化会更快的反映到其他线程内存,是快和慢的区别,不是有和无的区别。

《Java并发编程实战》却说,如果不用volatile修饰goon,那么在-server模式下,while (goon) {} 会被优化成 if (goon) while (true) {} 。但是我用实际代码验证了,并没有出现这种情况。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐