Best way of running two threads alternatively?

concurrency, java

Solution

Am I correct that the exchange method performs memory synchronization, just as much as using a Lock?

You are right. The javadoc specifies there is a happen-before relation:

"Memory consistency effects: For each pair of threads that successfully exchange objects via an Exchanger, actions prior to the exchange() in each thread happen-before those subsequent to a return from the corresponding exchange() in the other thread."

What do you think is the best solution?

Both are equivalent. You should target expressiveness. I find the synchronisation/Lock/Monitor based solution more expressive than the exchanged based one. But it does not really matter if you abstract this code in a dedicated class.

Am I doing it right, or do I miss another obvious solution?

AFAIK no If you don't want to re-implement the wheel.

Please note that your ReentrantLock based solution can also be written using plain old synchronisation or Monitor from Guava.

See: http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/util/concurrent/Monitor.html for a comparison.

And I didn't find that the CyclicBarrier was making the code simpler... (actually I didn't totally understand how to use it, but it didn't look simpler than using

CyclicBarrier does not fit your needs. It is not designed for mutual exclusion; it allows a set of threads to define a common barrier. Threads will execute concurrently and wait for each other at some point before moving to the next step.

Problem

Update: see bottom of this question for a complete answer. I want to run a secondary thread, so that my main thread and my secondary thread perform operations alternatively (no, I don't want to do all the operations in the main thread, it is for a unit test). I came up to two different solutions, I don't know which is the best, and I have questions regarding the first one: Using Exchanger I came up to something using an Exchanger (while I don't want to exchange only one object). ``` @Test public void launchMyTest() { /** * An anonymous class to set some variables from a different thread */ class ThreadTest extends Thread { //declare some various attributes that will be set //NOT DECLARED VOLATILE ... public final Exchanger<Integer> exchanger = new Exchanger<Integer>(); @Override public void run() { try { //start of the synchronization int turn = 1; while (turn != 2) { turn = this.exchanger.exchange(turn); } //do some work and set my various variables ... //main thread's turn turn = 1; this.exchanger.exchange(turn); //wait for this thread's turn while (turn != 2) { turn = this.exchanger.exchange(turn); } //redo some other work and reset the various variables ... //main thread's turn turn = 1; this.exchanger.exchange(turn); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } try { //some work in the main thread .... //launch the job in the second thread ThreadTest test = new ThreadTest(); test.start(); //start of the synchronization int turn = 2; test.exchanger.exchange(turn); //wait for this thread's turn while (turn != 1) { turn = test.exchanger.exchange(turn); } //run some tests using the various variables of the anonymous class .... //now, relaunch following operations in the second thread turn = 2; test.exchanger.exchange(turn); //wait for this thread's turn while (turn != 1) { turn = test.exchanger.exchange(turn); } //do some other tests using the various variables of the anonymous class //... } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } ``` Question: - Am I correct that the `exchange` method performs memory synchronization, just as much as using a `Lock`? Using Condition Another solution using a Condition: ``` @Test public void launchMyTest() { /** * An anonymous class to set some variables from a different thread */ class ThreadTest extends Thread { //declare some various attributes that will be set //NOT DECLARED VOLATILE ... public final Lock lock = new ReentrantLock(); public final Condition oneAtATime = lock.newCondition(); public int turn = 1; @Override public void run() { this.lock.lock(); try { //do some work and set my various variables ... //main thread's turn this.turn = 1; this.oneAtATime.signal(); //wait for this thread's turn while (this.turn != 2) { this.oneAtATime.await(); } //redo some other work and reset the various variables ... //main thread's turn this.turn = 1; this.oneAtATime.signal(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { this.lock.unlock(); } } } ThreadTest test = new ThreadTest(); test.lock.lock(); try { //some work in the main thread .... //launch the job in the second thread test.turn = 2; test.start(); //wait for this thread's turn while (test.turn != 1) { test.oneAtATime.await(); } //run some tests using the various variables of the anonymous class .... //now, relaunch following operations in the second thread test.turn = 2; test.oneAtATime.signal(); //wait for this thread's turn while (test.turn != 1) { test.oneAtATime.await(); } //do some other tests using the various variables of the anonymous class //... } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { test.lock.unlock(); } } ``` It seems to me a bit more complicated. Conclusion What do you think is the best solution? Am I doing it right, or do I miss another obvious solution? I didn't use a `CountDownLatch` as I want to run several operations alternatively, and the `CountDownLatch` cannot be reset. And I didn't find that the `CyclicBarrier` was making the code simpler... (actually I didn't totally understand how to use it, but it didn't look simpler than using `Exchanger` or `Condition`) Thank you. Update @Clément MATHIEU provided different examples of how to achieve this, in comments of its accepted answer, see: https://gist.github.com/cykl/5131021 There are three examples, one using a `CyclicBarrier`, another one using an `Exchanger`, and a last one using 2 `Semaphore`s. While he is right to say that the "more expressive is the semaphore based one", I chose to use an `Exchanger` for simplicity. My unit test became: ``` @Test public void launchMyTest() { /** * An anonymous class to set some variables from a different thread */ class ThreadTest extends Thread { //declare some various attributes that will be set //NOT DECLARED VOLATILE ... public final Exchanger<Integer> exchanger = new Exchanger<Integer>(); @Override public void run() { try { //do some work and set my various variables ... //main thread's turn this.exchanger.exchange(null); //wait for this thread's turn this.exchanger.exchange(null); //redo some other work and reset the various variables ... //main thread's turn this.exchanger.exchange(null); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } try { //some work in the main thread .... //launch the job in the second thread ThreadTest test = new ThreadTest(); test.start(); //wait for this thread's turn test.exchanger.exchange(null); //run some tests using the various variables of the anonymous class .... //now, relaunch following operations in the second thread test.exchanger.exchange(null); //wait for this thread's turn test.exchanger.exchange(null); //do some other tests using the various variables of the anonymous class //... } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } ```

Original source