Java语言规范第3版的8.3.1.4节表明了volatile field是线程可见的,各线程都可以看到最近数据,有JMM(Java Memory Model)保证(不知道具体怎么实现的?),但并不提供锁的保证。
Brain在这篇文章比较详细的说了一下Volatile的用法,Brain写的书<Java Concurreny in Pratice>,不错,比较简单实用,香比较Doug Le那本经典比较通俗一些,正在看。
Brain提了2条使用volatile的原则:
- Writes to the variable do not depend on its current value.
- The variable does not participate in invariants with other variables.
也就是说voliatle不能用做线程安全的计数器,使用volatile的动力是cheap
使用方法
1 status flag, 但状态必须是不依赖的(感觉这个模式用的最多)
2 one-time safe publication 例如引用的初始化,避免如double-check的问题,但在初始化过后引用对象的状态不能改变了
3 independent observations 2的延伸,状态可变,但不依赖其他状态 (其实每种都差不多?)
4 the "volatile bean" pattern 没什么用,没看谁这么用过
5 The cheap read-write lock trick
public class CheesyCounter {
private volatile int value;
public int getValue() { return value; }
public synchronized int increment() {
return value++;
}
}
形成了一个写是互斥而读是共享的机制,在大部分操作都是读的时候获得性能优势
在wiki上查了一下,它对volatile变量的解释是,对于声明为volatile的变量,就是告诉编译器这个变量有可能会被别的线程改变,不可以进行自以为是的优化
例如
代码
static int foo;
void bar(void)
{
foo = 0;
while (foo != 255)
continue;
}
可能会被优化成
void bar_optimized(void)
{
foo = 0;
while (TRUE)
continue;
}
(这是抄的wiki,不涉及版权问题吧?:))
在另一页里说到了C语言volatile的用法,用在硬件驱动的编写上