Exchanger Vs CountDownLatch

327 views Asked by At

I was wondering if anyone has used the java.util.concurrent.Exchanger class. According to java docs an Exchanger can be used to share some data between a pair for threads. The below sample is a typical usecase of reading and writing data and interaction between threads.

class FillAndEmpty {
   Exchanger<DataBuffer> exchanger = new Exchanger<DataBuffer>();
   DataBuffer initialEmptyBuffer = ... a made-up type
   DataBuffer initialFullBuffer = ...

   class FillingLoop implements Runnable {
     public void run() {
       DataBuffer currentBuffer = initialEmptyBuffer;
       try {
         while (currentBuffer != null) {
           addToBuffer(currentBuffer);
           if (currentBuffer.isFull())
             currentBuffer = exchanger.exchange(currentBuffer);
         }
       } catch (InterruptedException ex) { ... handle ... }
     }
   }

   class EmptyingLoop implements Runnable {
     public void run() {
       DataBuffer currentBuffer = initialFullBuffer;
       try {
         while (currentBuffer != null) {
           takeFromBuffer(currentBuffer);
           if (currentBuffer.isEmpty())
             currentBuffer = exchanger.exchange(currentBuffer);
         }
       } catch (InterruptedException ex) { ... handle ...}
     }
   }

   void start() {
     new Thread(new FillingLoop()).start();
     new Thread(new EmptyingLoop()).start();
   }
 } 

The same could have been done with two CountDownLatch s. One for writing to Buffer and one to notify the writer once all the reader threads have processed the records. So my question is

  1. What is the ideal use of Exchanger
  2. What are its pros and cons over say a CountDownLatch
2

There are 2 answers

2
Alexei Kaigorodov On

With CountDownLatches, you have to place references to buffers somewhere so that they are accessible to both threads (or pass references to the constructors). This increases the size of program code. Then, you have to recreate CountDownLatch for each transaction.

Other approaches are:

  • use pair of Semaphores instead of CountDownLatches - need not to recreate
  • use pair of ArrayBlockingQueues - need not to recreate, need not to worry about references to bufferes, and better parallelism than when using Exchanger.

UPDT Exchanger is a pair of blocking queues of size 1 each, with single operation exhange which is equivalent to queue1.put(value); return queue2.take();. So the only case when its using is justified, is when you need a pair of blocking queues of size 1 and always call put and get simultaneously. This is a rare case and I cannot see a reason why it was included in the standard java library.

0
Mister Smith On

CountDownLatch is a synchronization mechanism. You initialize an instance to a fixed count value N, then await until some other threads decrement this counter to 0. Its often used to make a thread wait for other N different threads to complete. But of course there are many other applications.

Exchanger is a communication mechanism. It lets you pass an object from thread T1 to T2 and at the same time pass back an object from T2 to T1. The swapping is blocking so you can use it as a synchronization mechanism as well, but this is not what it is meant for.