Java中的static和volatile

来源:互联网 发布:上海广通网络 编辑:程序博客网 时间:2024/05/16 18:38

《Effective Java》的并发章节讲了一个线程通信问题的例子,非常好的说明了如何由于失误代码导致的线程间通信失败,没有保证一个线程的所作的修改可以被另一个线程获知,也就是活性失败和安全性失败。回头想想,这样的失误(或者根本就不是失误,而是程序员们功力不到家)在工作中太常见了,特别是如果线上系统存在这样的代码,简直就是埋下了地雷。

作者的例子如下(有改动,但不影响):

    private static boolean stopRequested;    public static void main(){        Thread t = new Thread(new Runnable(){            public void run(){                int i = 0;                while(!stopRequested){                ++i;                }            }        });        t .start();        TimeUnit.SECOND.sleep(1);        stopRequested = true;    }

程序员的本意是希望设置 stopRequested = true 后,线程 t 能退出,但并不能达到预期效果。因为类的 static 变量虽然对 Java 的多个对象而言就是唯一的一份拷贝,无论创建了多少个对象。但对于线程,static 变量跟普通变量一样,每个线程自己缓存了一份本地拷贝,t1 改变了变量的值,对于 t2 并不可见,也就是单纯地定义变量为 static 还不够,必须同时声明为 volatile (或者同步锁改变 stopRequested 的值),这样 t1 跟 t2 才能正常通信(针对上述例子而言)。

这篇文章本意是讲一讲 static 跟 volatile 。so,现在问题来了,如果只声明 stopRequested 为 volatile ,上述的问题还会存在吗?答案是肯定的。定义为 volatile ,跟普通变量一样,是每个线程的一个本地拷贝,线程间并不能感知变量值的变化。声明为 static volatile,会迫使线程每次读取时作为一个全局变量读取。

原创粉丝点击