java - 防止 Java 中的 JIT 重新排序

标签 java multithreading jit

我有一个方法,看起来像是由 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 容器是“this”的一个字段,由 someThread 访问。当通过 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 节的阅读中,我认为我已经创建了一个具有法律约束力的happens-before,这将阻止重新排序,因为我现在在写入后从 wayPoints 中读取......“如果 x 和y 是同一线程的操作,x 按程序顺序出现在 y 之前,然后是 hb(x, y)。”

谢谢!

最佳答案

您完全正确,您已经创建了发生之前的关系。 一般来说

a = X; ( X 是一些不涉及 a 和 b 的常量或表达式) b=Y; ( Y 是一些不涉及 a 和 b 的常量或表达式)

以上两个可以通过 JIT 重新排序

但是 a = X ; b = a * Y;

不会重新排序。这几乎就是您在更正中所做的事情。

解决问题的其他方法是声明 wayPoints volatile 。如果将 wayPoints 声明为 volatile ,则写入 volatile ( wayPoints) 不会与原始程序顺序中的其他内存操作 ( someThread.addToQueue() ) 重新排序。

关于java - 防止 Java 中的 JIT 重新排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19649588/

相关文章:

java - 现场阴影还是覆盖?

java - 删除 UI 线程中已发送的消息

C# JIT 编译和 .NET

c# - JIT 编译器的 IL 优化

Java代码和JIT编译

java - 静态初始化的 unmodifiableCollection.get 是否保证不可变?

java - 服务器在 nio 中不接受多个客户端

java - 在使用它之前,必须配置该插件。请从系统配置中执行此操作

c# - 线程会提高性能吗?

Java如何向线程传递额外的对象