13. Synchronization Mechanisms in Java
π‘ Java provides several synchronization mechanisms to manage access to shared resources in a concurrent environment. Below are some commonly used mechanisms:
1. Semaphoresβ
A semaphore is a counting synchronization mechanism that can control access to a resource by multiple threads. It maintains a set number of permits, which can be acquired or released by threads.
Usageβ
- Counting Semaphore: Allows a set number of threads to access a resource.
- Binary Semaphore: Similar to a mutex, it can be either free (1) or locked (0).
Example:β
import java.util.concurrent.Semaphore;
public class SemaphoreExample {
private static final Semaphore semaphore = new Semaphore(1);
public void accessResource() {
try {
semaphore.acquire(); // Acquire a permit
// Access the shared resource
System.out.println("Resource is being accessed.");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release(); // Release the permit
}
}
}
2. Locksβ
Locks are more flexible than synchronized blocks and methods. Java provides several lock implementations in the java.util.concurrent.locks package, allowing for more advanced thread synchronization.
2.1. ReentrantLockβ
A ReentrantLock allows threads to acquire a lock and can be re-entrant (a thread can acquire the lock multiple times).
Example:β
import java.util.concurrent.locks.ReentrantLock;
public class LockExample {
private final ReentrantLock lock = new ReentrantLock();
public void safeMethod() {
lock.lock(); // Acquire the lock
try {
// Access the shared resource
System.out.println("Resource is being accessed.");
} finally {
lock.unlock(); // Ensure the lock is released
}
}
}
2.2. ReadWriteLockβ
A ReadWriteLock allows multiple readers or one writer at any point in time, improving concurrency for read-heavy applications.
Example:β
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadWriteLockExample {
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
public void readMethod() {
rwLock.readLock().lock(); // Acquire the read lock
try {
// Read from the shared resource
System.out.println("Resource is being read.");
} finally {
rwLock.readLock().unlock(); // Release the read lock
}
}
public void writeMethod() {
rwLock.writeLock().lock(); // Acquire the write lock
try {
// Write to the shared resource
System.out.println("Resource is being written.");
} finally {
rwLock.writeLock().unlock(); // Release the write lock
}
}
}
3. CountDownLatchβ
A CountDownLatch allows one or more threads to wait until a set of operations being performed in other threads completes.
Example:β
import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
private final CountDownLatch latch = new CountDownLatch(3); // Wait for 3 tasks
public void task() {
// Perform some work
System.out.println("Task completed.");
latch.countDown(); // Decrement the count
}
public void waitForCompletion() throws InterruptedException {
latch.await(); // Wait until the count reaches zero
System.out.println("All tasks are completed.");
}
}
4. CyclicBarrierβ
A CyclicBarrier allows a set of threads to wait for each other to reach a common barrier point. It can be reused after the barrier is tripped.
Example:β
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierExample {
private final CyclicBarrier barrier = new CyclicBarrier(3); // Wait for 3 threads
public void waitAtBarrier() {
try {
// Wait for other threads
System.out.println("Waiting at the barrier.");
barrier.await(); // Wait for the barrier
System.out.println("Passed the barrier.");
} catch (Exception e) {
e.printStackTrace();
}
}
}
5. Phaserβ
A Phaser is a more flexible synchronization barrier than a CyclicBarrier, allowing multiple phases of computation where threads can register and deregister dynamically.
Example:β
import java.util.concurrent.Phaser;
public class PhaserExample {
private final Phaser phaser = new Phaser(1); // Register main thread
public void phaseTask() {
phaser.arriveAndAwaitAdvance(); // Wait for other threads to reach this phase
System.out.println("Phaser phase completed.");
}
public void startPhases() {
// Register other threads dynamically
phaser.register();
// Call phaseTask() in multiple threads
}
}
Summary of Synchronization Mechanismsβ
| Mechanism | Description |
|---|---|
| Semaphore | Controls access with permits; allows multiple threads. |
| Lock | More flexible synchronization mechanism (e.g., ReentrantLock). |
| ReadWriteLock | Allows multiple readers or one writer at a time. |
| CountDownLatch | Allows threads to wait until a set of operations completes. |
| CyclicBarrier | Allows threads to wait for each other at a common point. |
| Phaser | More flexible barrier for multiple phases of computation. |
This overview covers various synchronization mechanisms in Java to help manage concurrency and ensure thread safety.