Java Reference
In-Depth Information
Synchronizers
I have discussed how to coordinate access to a critical section by multiple threads using a mutually exclusive
mechanism of intrinsic locks and explicit locks. Some classes known as synchronizers are used to coordinate the
control flow of a set of threads in a situation that needs other than mutually exclusive access to a critical section.
A synchronizer object is used with a set of threads. It maintains a state, and depending on its state, it lets a thread pass
through or forces it to wait. This section will discuss four types of synchronizers:
Semaphores
Barriers
Latches
Exchangers
Other classes can also act as a synchronizer such as a blocking queue.
Semaphores
A semaphore is used to control the number of threads that can access a resource. A synchronized block also controls
the access to a resource that is the critical section. So, how is a semaphore different from a synchronized block?
A synchronized block allows only one thread to access a resource (a critical section), whereas a semaphore allows N
threads (N can be any positive number) to access a resource.
If N is set to one, a semaphore can act as a synchronized block to allow a thread to have mutually exclusive
access to a resource. A semaphore maintains a number of virtual permits. To access a resource, a thread acquires a
permit and it releases the permit when it is done with the resource. If a permit is not available, the requesting thread is
blocked until a permit becomes available. You can think of a semaphore's permit as a token.
Let's discuss a daily life example of using a semaphore. Suppose there is a restaurant with three dining tables.
Only three people can eat in that restaurant at a time. When a person arrives at the restaurant, he must take a
token for a table. When he is done eating, he will return the token. Each token represents a dining table. If a person
arrives at the restaurant when all three tables are in use, he must wait until one is available. If a table is not available
immediately, you have a choice to wait until one becomes available or to go to another restaurant. Let's simulate this
example using a semaphore. You will have a semaphore with three permits. Each permit will represent a dining table.
The Semaphore class in the java.util.concurrent package represents the semaphore synchronizer. You create a
semaphore using one of its constructors, like so:
final int MAX_PERMITS = 3;
Semaphore s = new Semaphores(MAX_PERMITS);
Another constructor for the Semaphore class takes fairness as the second argument as in
final int MAX_PERMITS = 3;
Semaphore s = new Semaphores(MAX_PERMITS, true); // A fair semaphore
The fairness of a semaphore has the same meaning as that for locks. If you create a fair semaphore, in the situation
of multiple threads asking for permits, the semaphore will guarantee first in, first out (FIFO). That is, the thread that
asked for the permit first will get the permit first.
To acquire a permit, use the acquire() method. It returns immediately if a permit is available. It blocks if a
permit is not available. The thread can be interrupted while it is waiting for the permit to become available. Other
methods of the Semaphore class let you acquire one or multiple permits in one go.
To release a permit, use the release() method.
 
Search WWH ::




Custom Search