javamultithreadingmemoryexecutorhappens-before

Java memory consistency for Executor's worker threads


According to javadoc, an implementation of Executor must comply with:

Memory consistency effects: Actions in a thread (A) prior to submitting a Runnable object to an Executor happen-before its execution begins, perhaps in another thread (B).

Pheraps due to my poor English, it is not clear to me which memory-consistency relation is guaranteed (if any) between B and another potential thread C subsequently submitted by A to the same Executor. I hope the following example will clarify my doubt.

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?

    }

}

Is guaranteed that emc.a == 2 for the thread executing emc.mr2.run()? (In my tests that is always true, but...yes, they are tests) If not, is there interface in the official API that ensure that emc.a == 2?


Solution

  • No it is not guaranteed because you change value of emc.a in one thread but submit Runnable from another thread. If you submit second runnable from first runnable after it set value to 2 then memory consistency effect from JavaDoc will be applicable.

    But in your example usage of volatile variable isDone will do the trick even without taking into account that note from JavaDoc. Since you first increment emc.a, then set new value to isDone and then check isDone it sill establish happens before relation and second runnable will always see updated value.