We talk about synchronization when more than one concurrent task shares a resource.
The blocks of code that access this shared resource are called critical sections.
The high-level mechanisms are:
- Semaphores: A semaphore is a counter that controls the access to one or more shared resources.
- CountDownLatch: The CountDowLatch class is a mechanism provided by the Java language that allows a thread to wait for the finalization of multiple operations.
- CyclicBarrier: The CyclicBarrier class is another mechanism provided by the Java language that allows the synchronization of multiple threads in a common point.
- Phaser: The Phaser class is another mechanism provided by the Java language that controls the execution of concurrent tasks divided in phases. All the threads must finish one phase before they can continue with the next one.
- Exchanger: The Exchanger class is another mechanism provided by the Java language that provides a point of data interchange between two threads.
Controlling concurrent access to a resource
A semaphore is a counter taht protects the access to one or more shared resources.
When a thread wants to access one of these shared resources, first, it must acquire that semaphore. If the internal counter of the semaphore is greater than 0, the semaphore decrements the counter and allows access to the shared resource. A counter bigger than 0 means there are free resources that can be used, so the thread can access and use one of them.
When the thread has finished the use of the shared resource, it must release the semaphore so that the other thread can access the shared resource. That operation increases the internal counter of the semaphore.
Binary semaphores protect the access to a unique shared resource, so the internal counter of the semaphore can only take the values of 1 or 0.
Fairness in semaphores
The default mode is called the non-fair mode. In this mode, when the synchronization resources 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.
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.