标签:volatile
Java语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量。这两种机制的提出都是为了线程 B 读一个 volatile 变量,实质上是线程 B 接收了之前某个线程发出的(在写这个 volatile 变量之前对共享变量所做修改的)消息。
线程 A 写一个 volatile 变量,随后线程 B 读这个 volatile 变量,这个过程实质上是线程 A 通过主内存向线程 B 发送消息。
JMM(java内存模型)的支持原理
volatile用来确保将变量的更新操作通知到其它线程。当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量时共享的,因此不会将该变量的操作与其它内存操作一起重排序。volatile变量不会被缓存在寄存器或者对其它处理器不可见的地方,因此在读取volatile类型的变量时总会返回最新写入的值。严格限制编译器和处理器对 volatile 变量与普通变量的重排序,确保 volatile 的写-读和锁的释放-获取具有相同的内存语义。从编译器重排序规则和处理器内存屏障插入策略来看,只要 volatile 变量与普通变量之间的重排序可能会破坏 volatile 的内存语义,这种重排序就会被编译器重排序规则和处理器内存屏障插入策略禁止。编译器在生成字节码时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序。
volatile变量对可见性的影响比volatile变量本身更为重要。当线程A首先写入一个volatile变量并且线程B随后读取该变量时,在写入volatile变量之前对A可见的所有变量的值,在B读取了volatile变量后,对B也是可见的。因此,从内存可见性的角度来看,写入volatile变量相当于退出同步代码块,而读取volatile变量就相当于进入同步代码块。我们可以简单理解为当要读取一个volatile变量时总是伴随着先要到主内存刷新取到最新值,而写变量时会把值直接写到主内存以对其它线程可见,这些都是由JMM(java内存模型)禁止指令重排序做保证的。不建议过度依赖volatile变量提供的可见性。如果在代码中依赖volatile变量来控制状态的可见性,通常比使用锁的代码更脆弱,也更难理解。
volatile典型用法
仅当volatile变量能简化代码的实现以及对同步策略的验证时,才应该使用它们。如果在验证正确性时需要对可见性进行复杂的判断,那么就不要使用volatile变量。volatile变量的正确使用方式包括:确保它们自身状态的可见性,确保他们所引用对象的状态的可见性,以及标示一些重要的程序声明周期事件的发生,如初始化或关闭。
volatile boolean asleep; ... while(!asleep) countSomeSheep();
参考文献:
java并发编程实战,
深入理解JVM
理解java中的volatile关键字,布布扣,bubuko.com
标签:volatile
原文地址:http://blog.csdn.net/lgcssx/article/details/38324817