执行程序工作线程的 Java 内存一致性



根据javadoc,Executor的实现必须符合:

内存一致性影响:在将 Runnable 对象提交到执行器之前,线程 (A) 中的操作在其执行开始之前发生,可能在另一个线程 (B) 中发生。

由于我的英语很差,我不清楚 BA 随后提交给同一执行人的另一个潜在线程 C 之间保证了哪种内存一致性关系(如果有的话)。我希望下面的例子能澄清我的疑问。

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
class ExecutorTestClass {
    int a = 1;
    volatile boolean isDone = false;
    MyRunnable mr1 = new MyRunnable("One");
    MyRunnable mr2 = new MyRunnable("Two");
    class MyRunnable implements Runnable {
    private final String name;
    MyRunnable(String name) {
        this.name = name;
    }
    @Override
    public void run() {
        System.out.println(name + ": " + ExecutorTestClass.this.a++);
        isDone = true; // signal that addition has been performed
        while (true) {
        try {
            Thread.sleep(5); // busy thread
        } catch (InterruptedException e) {
        }
        }
    }
    }
    public static void main(String[] args) {
    ExecutorTestClass emc = new ExecutorTestClass();
    Executor executor = Executors.newFixedThreadPool(2);
    executor.execute(emc.mr1); // run the first MyRunnable
    while (!emc.isDone) {
    } // when stop spinning emc.a == 2 for this thread
    executor.execute(emc.mr2); // is emc.a == 2 guaranteed?
    }
}

是否保证执行emc.mr2.run()的线程emc.a == 2?(在我的测试中,这总是正确的,但是...是的,它们是测试)如果没有,官方 API 中是否有接口可以确保emc.a == 2

不,不能保证,因为您更改了一个线程中的emc.a值,但从另一个线程提交Runnable。如果在将值设置为 2 后从第一个可运行提交第二个可运行对象,则 JavaDoc 的内存一致性效果将适用。

但是在您的示例中,即使不考虑 JavaDoc 的注释,volatile变量的使用isDone也可以解决问题。由于您首先递增emc.a,然后将新值设置为 isDone 然后检查它isDone在关系之前建立,第二个可运行对象将始终看到更新的值。

最新更新