2008年10月4日星期六

一个随便写写的测试Java reordering的程序

程序很简单,就是有一个类Obj不停的被实例化
class Obj {
int x;
public Obj(int x) {
this.x = x;
}
}
这个类总是被一个线程传入参数100不停的构造,另外一个线程读取,理论上另一个线程可能只会看到x=100对么?其实不是,如果java -server来执行这个程序你会看到很多x=0的情况出现。为什么呢?就是因为reordering的优化
如果你给x加上volatile或者final关键字你就不会看到这个问题了,或者给obj加上volatile也可以。
因为这两个关键字都禁止reordering,在JDK1.4里或许不行,但是JDK5重新规定了volatile的行为,其中包括了不仅和volatile变量之间禁止reordering,也和non-volatile变量之间禁止reordering了。
final这里可能更好一些,因为Obj这样就是一个immutable对象了,而我们Obj的构造函数并没有escape this到外部线程,所以可以获得JDK5的所谓Initialization Safety的特性,保证了final字段x一定是不需要同步就可以被外部线程看到,这蕴含着禁止reordering.


package test.jmm;

public class TestReordering {
public Obj obj=null;

public static void main(String[] args) {
TestReordering test = new TestReordering();
new WriterThread(test).start();
new ReaderThread(test).start();
}
}

class Obj {
int x;
public Obj(int x) {
this.x = x;
}
}

class WriterThread extends Thread {
private TestReordering test;
public WriterThread(TestReordering test) {
this.test = test;
}
public void run() {
while(true) {
test.obj = new Obj(100);
}
}
}
class ReaderThread extends Thread {
private TestReordering test;
public ReaderThread(TestReordering test) {
this.test = test;
}
public void run() {
while(true) {
if (test.obj != null)
if(test.obj.x == 0) {
System.out.println("found");
} else {
//System.out.println(test.obj.x);
}
}
}
}

没有评论: