In our previous series of Mutex and Semaphore , we learn about the different Synchronizers.Now we discuss about one of them that is CountDownLatch.Let's take the understanding of CountDownLatch With the help of an example.
Let's take a real life scenario.Suppose we get a new project from a client.We have one architect and 10 developers.First the architect will design the project and decide the technologies to use.He will decide about the project flow and create the different modules.But till then all the developers need to wait for the architect to finish all his work.It means developers are coming to office but they are not doing anything useful.Because they have dependency on the architect.Just think they are waiting for a lock to be released by architect.After the lock is released by the architect the developers will get go ahead.Then they will start to work on there assigned module.Assume till the time the architect is waiting for completion of the task which is going on by developers.Just think that he is waiting for the lock to be released by developers.Remember that he can not proceed until all the developers have completed their work.If 5 developers have completed their work,then he still has to wait for remaining 5 developers.Then after the architect will proceed to review all the pieces of code and integrate them.This scenario is perfectly suitable for use of a CountDownLatch.
Definition:CountDownLatch is a synchronization aid or a synchronizer that allows one or more threads to wait for one or more other threads to complete.
Implementation In Java:
To implement java provides a class know as CountDownLatch.We can create a CountDownLatch object with integer argument like
CountDownLatch architectLatch = new CountDownLatch(1);
CountDownLatch developerLatch = new CountDownLatch(10);
Let's take a real life scenario.Suppose we get a new project from a client.We have one architect and 10 developers.First the architect will design the project and decide the technologies to use.He will decide about the project flow and create the different modules.But till then all the developers need to wait for the architect to finish all his work.It means developers are coming to office but they are not doing anything useful.Because they have dependency on the architect.Just think they are waiting for a lock to be released by architect.After the lock is released by the architect the developers will get go ahead.Then they will start to work on there assigned module.Assume till the time the architect is waiting for completion of the task which is going on by developers.Just think that he is waiting for the lock to be released by developers.Remember that he can not proceed until all the developers have completed their work.If 5 developers have completed their work,then he still has to wait for remaining 5 developers.Then after the architect will proceed to review all the pieces of code and integrate them.This scenario is perfectly suitable for use of a CountDownLatch.
Definition:CountDownLatch is a synchronization aid or a synchronizer that allows one or more threads to wait for one or more other threads to complete.
Implementation In Java:
To implement java provides a class know as CountDownLatch.We can create a CountDownLatch object with integer argument like
CountDownLatch architectLatch = new CountDownLatch(1);
CountDownLatch developerLatch = new CountDownLatch(10);
Let's consider our example that we have 10 developers all are
waiting on architectLatch by calling architectLatch.await() method.Here await() method will cause the calling threads(i.e our
developer threads) to wait until the latch has counted down to zero.Then after completing its work the architect thread will call
architectLatch.countDown().The countDown() method decreases the count of
the latch by 1.Now architect thread will wait by calling
developerLatch.await().If the count of the latch reaches at zero , then
all the threads waiting on this CountDownLatch (ie. architectLatch) will
start.
After completing their work each developer thread will call developerLatch.countDown(). When all the developer threads complete then the count of the developerLatch will be zero and architect thread will resume and start working.Take a look at the implementation details.
import java.util.concurrent.CountDownLatch;
public class Architect {
public static void main(String args[]) throws InterruptedException {
final int totalNosOfLatchCount=10;
CountDownLatch architectLatch = new CountDownLatch(1);
CountDownLatch developerLatch = new CountDownLatch( totalNosOfLatchCount); for (int i = 0; i < totalNosOfLatchCount; ++i)
new Thread(new Developer(architectLatch, developerLatch)).start();
completeModuleDesign();
architectLatch.countDown();
System.out.println("Architect has decreased the count of architectLatch and
After completing their work each developer thread will call developerLatch.countDown().
import java.util.concurrent.CountDownLatch;
public class Architect {
public static void main(String args[]) throws InterruptedException {
final int totalNosOfLatchCount=10;
CountDownLatch architectLatch = new CountDownLatch(1);
CountDownLatch developerLatch = new CountDownLatch(
new Thread(new Developer(architectLatch, developerLatch)).start();
completeModuleDesign();
architectLatch.countDown();
System.out.println("Architect has decreased the count of architectLatch and
going to wait on developerLatch.");
developerLatch.await();
System.out.println("Now all the developers have completed there work and architect is going to resume.");
}
public static void completeModuleDesign(){
System.out.println("Architect has completed the design of all his module. ");
}
}
developerLatch.await();
System.out.println("Now all the developers have completed there work and architect is going to resume.");
}
public static void completeModuleDesign(){
System.out.println("Architect has completed the design of all his module. ");
}
}
import java.util.concurrent.CountDownLatch;
public class Developer implements Runnable {
private final CountDownLatch architectLatch;
private final CountDownLatch developerLatch;
Developer(CountDownLatch startSignal, CountDownLatch doneSignal) {
this.architectLatch = startSignal;
this.developerLatch = doneSignal;
}
public void run() {
try {
architectLatch.await();
completeDevloperModule();
developerLatch.countDown();
System.out.println("Each developer has decreased the count on developerLatch by one.\nAnd number of avaialble count on developerLatch is "+developerLatch.getCount());
} catch (InterruptedException ex) {} // return;
}
void completeDevloperModule() {
System.out.println("Developer is completing his own module");
}
}
At first glance it seems like we can achieve this with the help of wait ,notify and join mechanism.But CountDownLatch is more forgiving in the case of missed signal.Consider a scenario , if one thread is waiting and another thread is notifying him,but just assume that the thread1, call it notifying thread, started first and it notified the the thread which is supposed to receive the notification signal,which is not started yet.But the thread which need to receive the notification signal started after that.Now the second thread which need to receive the notification signal will be in a stall state, because it missed the notification signal issued by the first thread.But in this case CountDownLatch will serve perfectly well.That is if count is down first and await method will invoked later,there will be no missed signal issue.
public class Developer implements Runnable {
private final CountDownLatch architectLatch;
private final CountDownLatch developerLatch;
Developer(CountDownLatch startSignal, CountDownLatch doneSignal) {
this.architectLatch = startSignal;
this.developerLatch = doneSignal;
}
public void run() {
try {
architectLatch.await();
completeDevloperModule();
developerLatch.countDown();
System.out.println("Each developer has decreased the count on developerLatch by one.\nAnd number of avaialble count on developerLatch is "+developerLatch.getCount());
} catch (InterruptedException ex) {} // return;
}
void completeDevloperModule() {
System.out.println("Developer is completing his own module");
}
}
Reusability of CountDownLatch:
One important thing we need to note here that , after reaching the count zero,the CountDownLatch can't be reused.There is no method to increase the count of CountDownLatch.We can think of it as a benefit as no one can increase the count by mistake also.If we call again the await() method after the count reaches 0, there will be no result.Simply it will pass through that and will not throw any exception. Still if we want to reset the count for programming purpose, we can consider using CycclicBarrier.Comparison of CountDownLatch with wait(),notify() and join():
At first glance it seems like we can achieve this with the help of wait ,notify and join mechanism.But CountDownLatch is more forgiving in the case of missed signal.Consider a scenario , if one thread is waiting and another thread is notifying him,but just assume that the thread1, call it notifying thread, started first and it notified the the thread which is supposed to receive the notification signal,which is not started yet.But the thread which need to receive the notification signal started after that.Now the second thread which need to receive the notification signal will be in a stall state, because it missed the notification signal issued by the first thread.But in this case CountDownLatch will serve perfectly well.That is if count is down first and await method will invoked later,there will be no missed signal issue.
No comments:
Post a Comment