Согласованность памяти Java для рабочих потоков Executor

Согласно Javadoc, реализация Executor должен соответствовать:

Эффекты согласованности памяти: Действия в потоке (A) перед отправкой объекта Runnable исполнителю выполняются до начала его выполнения, возможно, в другом потоке (B).

Pheraps из-за моего плохого английского, мне не ясно, какое отношение согласованности памяти гарантировано (если есть) между B и другим потенциальным потоком C, впоследствии переданным A тому же Исполнителю. Я надеюсь, что следующий пример прояснит мои сомнения.

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.a == 2 для выполнения потока emc.mr2.run()? (В моих тестах это всегда верно, но... да, это тесты) Если нет, есть ли в официальном API интерфейс, который гарантирует, что emc.a == 2?

1 ответ

Решение

Нет, это не гарантируется, потому что вы меняете значение emc.a в одну ветку, но отправьте Runnable из другого потока. Если вы передаете второй runnable из первого runnable после того, как для него установлено значение 2, тогда будет применим эффект согласованности памяти из JavaDoc.

Но в вашем примере использование volatile переменная isDone сделает свое дело, даже не принимая во внимание эту заметку из JavaDoc. Так как вы первый шаг emc.aзатем установите новое значение isDone а затем проверьте isDone это будет установлено до того, как отношение и второй исполняемый файл всегда будут видеть обновленное значение.

Другие вопросы по тегам