我有一个看起来像是由 JIT 重新排序的方法。
public boolean finishRequest(boolean success) {
if (success) {
error = false;
wayPoints.put(FINISH_SUCCESS_WP, System.currentTimeMillis());
} else {
wayPoints.put(FINISH_ERROR_WP, System.currentTimeMillis());
error = true;
}
someThread.addToQueue(this);//...submit for further processing on separate thread
return true;
}
wayPoints 容器是由 someThread 访问的“this”字段。当它通过 getWayPoints() 遍历这个 wayPoints 时,我最终在 someThread 中的某行代码中得到了 ConcurrentModificationException。
为了解决这个问题,我创建了一个新的不可变类,它将被传递给 someThread 而不是“this”。
public boolean finishRequest(boolean success) {
if (success) {
error = false;
wayPoints.put(FINISH_SUCCESS_WP, System.currentTimeMillis());
} else {
wayPoints.put(FINISH_ERROR_WP, System.currentTimeMillis());
error = true;
}
PLog plog = new PLog(wayPoints.toArray(new WayPoint[wayPoints.size()]));
someThread.addToQueue(plog);//...submit for further processing on separate thread
return true;
}
在第一段代码中,JIT 可以重新排序 'someThread.addToQueue()' 和 'wayPoints.put()' 因为编译器可以告诉 wayPoints 没有被进一步读取到当前线程中。但是在固定代码中,由于我使用 wayPoints 来构造我的新 PLog 实例,我现在是否有效地阻止了 JIT 重新排序?
参考...... http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.5
从 JLS 的第 17.4.5 节的阅读中,我认为我已经创建了一个具有法律约束力的发生之前,这将阻止重新排序,因为我现在在写入之后从 wayPoints 读取......“如果 x 和 y 是动作在同一线程中,x 在程序顺序中位于 y 之前,然后是 hb(x, y)。”
谢谢你!