Semaphore CountDownLatch CyclicBarrier Phaser Exchanger
You already understand the low-level concurrency constructs (such as the use of the synchronized keyword, Runnable interface, and Thread class for creating threads). In the case of a shared resource that needs to be accessed by multiple threads, access and modifications to the shared resource need to be protected.
When you use the synchronized keyword, you employ mutexes to synchronize between threads for safe shared access. Threads also often needed to coordinate their executions to complete a bigger higher-level task. The wait/ notify pattern is one way to coordinate the execution of multiple threads.
Using APIs for acquiring and releasing locks (using mutexes) or invoking the wait/notify methods on locks are low-level tasks. It is possible to build higher-level abstractions for thread synchronization. These high-level abstractions for synchronizing activities of two or more threads are known as synchronizers. Synchronizers internally make use of the existing low-level APIs for thread coordination.
Five classes help common special-purpose synchronization idioms.
- Semaphore is a classic concurrency tool.
Semaphores are often used to restrict the number of threads than can access some (physical or logical) resource.
- CountDownLatch is a very simple yet very common utility for blocking until a given number of signals, events, or conditions hold.
A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes
- A CyclicBarrier is a resettable multiway synchronization point useful in some styles of parallel programming.
A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point. CyclicBarriers are useful in programs involving a fixed sized party of threads that must occasionally wait for each other. The barrier is called cyclic because it can be re-used after the waiting threads are released.
- A Phaser provides a more flexible form of barrier that may be used to control phased computation among multiple threads.
A reusable synchronization barrier, similar in functionality to CyclicBarrier and CountDownLatch but supporting more flexible usage.
- An Exchanger allows two threads to exchange objects at a rendezvous point, and is useful in several pipeline designs.
A synchronization point at which threads can pair and swap elements within pairs. Each thread presents some object on entry to the exchange method, matches with a partner thread, and receives its partner's object on return. An Exchanger may be viewed as a bidirectional form of a SynchronousQueue. Exchangers may be useful in applications such as genetic algorithms and pipeline designs.
If you know anyone who has started learning Java, why not help them out! Just share this post with them.
Thanks for studying today!...
If you want to get an idea of these two terms before looking into the differences. Please have a look at the following posts. These will explain both the terms with the help of real scenario examples.
CyclicBarrier in Java
CountDownLatch in Java
- CyclicBarrier as name suggest. CyclicBarrier can be used re-used after the waiting threads are released for synchronization. So the cyclic barrier is used for multiple synchronization points where as CountDownLatch is one synchronization point because we can't re-use it.
- CyclicBarrier takes an (optional) Runnable task which is run once the common barrier condition is met. where as in CountDownLatch there is no optional runnable task.
- When using a CyclicBarrier, the assumption is that you specify the number of waiting threads that trigger the barrier. If you specify 3, you must have at least 3 threads to call await(). When using a CountDownLatch, you specify the number of calls to countDown() that will result in all waiting threads being released.
- In CyclicBarrier If a thread leaves a barrier point prematurely because of interruption, failure, or timeout, all other threads waiting at that barrier point will also leave abnormally via BrokenBarrierException (or InterruptedException if they too were interrupted at about the same time). where as this is not present in CountDownLatch
Related Post
Semaphore in Java
How Thread exchange data in java
Semaphore vs CountDownLatch
How class are loaded in JVM
If you know anyone who has started learning Java, why not help them out! Just share this post with them. Thanks for studying today!...
In this post we'll see one of the synchronizers that is used in java.util.concurrent library i.e, Semaphore. We'll see a simplest and easiest way to use Semaphore so that it is easy to remember and understand easily.
What is Semaphore?
A semaphore controls access to shared resources. A semaphore maintains a counter to specify the number of resources that the semaphore controls.
Access to the resource is allowed if the counter is greater than zero,while a zero value of the counter indicates that no resource is available at the moment and so the access is denied. Semaphore: n-member access to a resource
A semaphore acts as a limiter of available resource pool depth; for example, a semaphore with a capacity of 10 allows a maximum of 10 threads to acquire it at once, and any further threads that attempt to acquire it will block until one of the other threads releases it.
This is somewhat different from ordinary mutual exclusion or monitor locking, which is typically used to prevent more than one thread from simultaneously modifying the same variables and causing inconsistent results or program state.
Synchronization vs Semaphore
Synchronized allows only one thread of execution to access the resource at the same time. Semaphore allows up to n threads of execution to access the resource at the same time.
Basically two method that used are for acquiring and releasing resources from a semaphore
- acquire() : decrement the value
- release() : increment the value
If a thread calls acquire() and the counter is zero (i.e., resources are unavailable), the thread waits until the counter is non-zero and then gets the resource for use. Once the thread is done using the resource, it calls release() to increment the resource availability counter.
Note if the number of resources is 1, then at a given time only one thread can access the resource; in this case, using the semaphore is similar to using a lock
A semaphore initialized to one, and which is used such that it only has at most one permit available, can serve as a mutual exclusion lock.This is more commonly known as a binary semaphore, because it only has two states.
Semaphores are often used to restrict the number of threads than can access some (physical or logical) resource.
- Semaphore(int permits) : This method create Semaphore objects with a given number of permits, here permits means the number of threads that can access the resource at a time.
- void acquire() : Acquires a permit if available; otherwise, it blocks until a permit becomes available
- void release() : Releases a permit from the semaphore basically decrement the value
Example First we see example of binary semaphore.To show how to use it, we are going to implement a print queue that can be used by concurrent tasks to print their jobs. This print queue will be protected by a binary semaphore, so only one thread can print at a time.
Output
How it works...
The key to this example is in the printJob() method of the PrintQueue class. This method shows the three steps you must follow when you use a semaphore to implement a critical section, and protect the access to a shared resource:
- First, you acquire the semaphore, with the acquire() method.
- Then, you do the necessary operations with the shared resource.
- Finally, release the semaphore with the release() method.
Another important point in this example is the constructor of the PrintQueue class and the initialization of the Semaphore object. You pass the value 1 as the parameter of this constructor, so you are creating a binary semaphore. The initial value of the internal counter is 1, so you will protect the access to one shared resource, in this case, the print queue.
The Semaphore class has two additional versions of the acquire() method:
- acquireUninterruptibly(): The acquire() method; when the internal counter of the semaphore is 0, blocks the thread until the semaphore is released. During this blocked time, the thread may be interrupted and then this method throws an InterruptedException exception. This version of the acquire operation ignores the interruption of the thread and doesn't throw any exceptions.
- tryAcquire(): This method tries to acquire the semaphore. If it can, the method returns the true value. But if it can't, the method returns the false value instead of being blocked and waits for the release of the semaphore. It's your responsibility to take the correct action based on the return value.
Fairness in semaphores
The concept of fairness is used by the Java language in all classes that can have various threads blocked waiting for the release of a synchronization resource (for example, a semaphore). The default mode is called the non-fair mode. In this mode, when the synchronization resource is released, one of the waiting threads is selected to get this resource, but it's selected without any criteria. The fair mode changes this behavior and forces to select the thread that has been waiting for more time.
As occurs with other classes, the Semaphore class admits a second parameter in its constructor. This parameter must take a Boolean value. If you give it the false value, you are creating a semaphore that will work in non-fair mode. You will get the same behavior if you don't use this parameter. If you give it the true value, you are creating a semaphore that will work in fair mode.
Controlling Concurrent access to multiple copies of a resource
In that recipe, you implemented an example using binary semaphores. These kinds of semaphores are used to protect the access to one shared resource, or to a critical section that can only be executed by one thread at a time. But semaphores can also be used when you need to protect various copies of a resource, or when you have a critical section that can be executed by more than one thread at the same time.
In this Example, you will learn how to use a semaphore to protect more than one copy of a resource. You are going to implement an example, which has one print queue that can print documents in three different printers.
Output
How it works...
The key of this example is in the PrintQueue class. The Semaphore object is created using 3 as the parameter of the constructor. The first three threads that call the acquire() method will get the access to the critical section of this example, while the rest will be blocked. When a thread finishes the critical section and releases the semaphore, another thread will acquire it.
In this critical section, the thread gets the index of the printer assigned to print this job. This part of the example is used to give more realism to the example, but it doesn't use any code related with semaphores.
The acquire(), acquireUninterruptibly(), tryAcquire(), and release() methods have an additional version which has an int parameter. This parameter represents the number of permits that the thread that uses them wants to acquire or release, so as to say, the number of units that this thread wants to delete or to add to the internal counter of the semaphore. In the case of the acquire(), acquireUninterruptibly(), and tryAcquire() methods, if the value of this counter is less this value, the thread will be blocked until the counter gets this value or a greater one.
If you know anyone who has started learning Java, why not help them out! Just share this post with them. Thanks for studying today!...