Согласованность памяти Java для рабочих потоков Executor - PullRequest
0 голосов
/ 29 января 2019

Согласно 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 Ответ

0 голосов
/ 29 января 2019

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

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

...