如果下面的代码不会在Windows7 x86 JDK7(打开了-ea )上为每个JLS example for volatile抛出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();
}
}
};发布于 2013-01-14 03:46:54
您有多个线程在运行one。i和j是易失性的,因此更改是可见的,但是i++和j++不是原子操作,并且很可能其中一个计数器在某个阶段不会正确递增:
例如,假设我是5,以显示可以抛出AssertionError的有效线程交错:
线程2: write I= temp => 6
并且i和j不同步,您在one中的断言将失败。
但是,尽管存在数据竞争,程序的运行仍有可能不抛出断言错误: JLS不保证您的程序将正常运行,但它也不会说它不会。
编辑:一个写了JLS的“线程和锁”部分的人实际上有一个关于非常类似问题的post on his blog。评论甚至提到了您在问题中提到的JLS部分:在JLS示例中只有一个编写线程。
https://stackoverflow.com/questions/14307277
复制相似问题