【发布时间】:2013-01-13 19:29:06
【问题描述】:
下面的代码是否应该不会根据JLS example for volatile 在 windows 7 x86 jdk 7(打开 -ea)上抛出 AssertionError?
public class TestVolatile {
static volatile int i = 0;
static volatile int j = 0;
static void one() {
i++;
j++;
assert (i>=j);
//:"one: i=" + i + " j=" + j;
}
static void two() {
//System.out.println("i=" + i + " j=" + j);
assert (i<=j);
/*
System.out.print("<i=" + i);
for (int k = 0; k < 1000000; k++);
System.out.println(", j=" + j+">");
*/
}
public static final int NUM_WORKERS = 4;
public static void main (String [] args) {
final Worker [] workers = new Worker[NUM_WORKERS];
final Thread [] workerThreads = new Thread[NUM_WORKERS];
for (int i = 0; i < NUM_WORKERS; i++) {
Worker w = new Worker(i);
workers[i] = w;
workerThreads[i] = new Thread(w,"workerThread_"+i);
}
for (int i = 0; i < NUM_WORKERS; i++) {
workerThreads[i].start();
}
}
}
final class Worker implements Runnable {
final int id;
volatile boolean notDone = true;
public Worker(int tid){
id = tid;
}
@Override
public void run() {
//System.out.println("worker start:" + id);
try {
while (notDone) {
if (id < TestVolatile.NUM_WORKERS - 1) {
TestVolatile.one();
} else {
TestVolatile.two();
}
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
};
【问题讨论】:
-
我几乎马上就收到了错误。
-
您预计会在哪里出错,为什么?澄清
-
我也得到了错误,没有任何延迟,而且确实如此。
-
@MarkoTopolnik 老实说,我发现example 8.3.1.4-1 底部的措辞有点误导:因此,j 的共享值永远不会大于 i,因为每次更新到在更新到 j 之前,i 必须反映在 i 的共享值中。
-
@assylias 即使对于单个作者来说,这个陈述也是错误的,甚至下一句也承认:“然而,任何给定的方法二调用都可能观察到j 远大于对 i 观察到的值,...”。所以 j 可以大于 i 并且在前面的句子中说否则是......充其量是误导。有a new Q&A 关于这个和恕我直言,这个例子应该在地狱中燃烧......
标签: java multithreading concurrency volatile jls