Thursday, July 31, 2008

Guarded Block in Java - what's it & why is it used?


Guarded Blocks in Java - what are they & why are they used?

This is one of the most popular mechanisms of co-ordinating the execution of multiple threads in a multithreaded application. Such a block keeps checking for a particular condition to become true and only in that case the actual execution of the thread resumes.

Why should a thread's execution required to be co-ordinated with that of other threads? There may be several reasons - one of them being, if multiple threads are modifying a shared data and one (or maybe more) threads can't really proceed unless the shared data acquires a particular value (otherwise the execution may cause some incosistency/business-error or something of that sort) then in such a case we can have a condition checking the value of that shared data in that particular thread and can allow the execution of the thread to proceed only when the condition is true.

Now what the thread will do until then? Based on how the thread reacts to a 'false' condition, guarded blocks are of two types:-

  • synchronized guarded block - in this case if the condition is false then the block (which is a synchronized block) simply calls the Object.wait() method to release the acquired monitors on that object and leaves the processor to be used by other threads (probably more effectively as the current thread would not have done anything significant in this case unless the condition becomes true).
  • non-synchronized guarded block - in this case we simply cause the execution to keep executing a blank loop until the condition becomes true. This approach has an obvious disadvantage of wasting the precious CPU time, which could have been better utilized by some other threads otherwise.

Example: synchronized guarded block - Java code snippet

public synchronized guardedBlock() {

while(!sharedBooleanFlag) {
try {
wait();
} catch (InterruptedException e) {}
}

System.out.println("Shared Boolean Flag is true - you may proceed now!");

}

non-synchronized guarded block - Java code snippet

public guardedBlock() {

while(!sharedBooleanFlag) {
//... empty loop
}


System.out.println("Shared Boolean Flag is true - you may proceed now!");

}

A thread which is in waiting state on an object may be interrupted/notified by some other thread either intentionally or accidentally and hence may start execution after getting re-scheduled, but that doesn't guarantee that the condition (which is required to be true for the thread to proceed further) has also become true and hence one needs to make sure that the wait() method is always called inside the loop which checks for the condition. If the thread wakes up and starts its execution before the condition becomes true then it'll immediately go to the waiting state once again which will obviously save the precious CPU time to be utilized by other threads and at the same time such an approach will always guarantee that the execution of the thread will proceed only in the expected manner.

Don't forget to ensure that the application has other threads which acquire locks on the objects (on which few other threads have previously called wait() method) and call either notify() and notifyAll() methods so that the application can avoid startvation of those threads which have called wait() on the objects under consideration. notifyAll() scheduled all the waiting threads whereas notify() randomly picks one of the waiting threads and schedules it. Use the method which suits the design of your application. Read more aout the differences between the two methods in this article - notify()vs notifyAll() >>.



Share/Save/Bookmark


No comments: