Category : Java | Sub Category : Java Threads | By Prasad Bonam Last updated: 2023-08-16 08:19:43 Viewed : 46
In Java, there are several types of locks that are used for synchronization and concurrency control to ensure that multiple threads can access shared resources in a controlled and coordinated manner. Here are some of the common types of locks in Java:
Synchronized Lock:
The synchronized
keyword is used to create intrinsic locks (also known as monitor locks) around critical sections of code. It provides mutual exclusion, allowing only one thread to execute the synchronized block of code at a time.
ReentrantLock:
The ReentrantLock
class from the java.util.concurrent.locks
package provides an explicit lock mechanism that allows more flexibility than synchronized
blocks. It supports reentrant locking, meaning a thread that holds the lock can re-enter the synchronized block without deadlocking itself.
ReadWriteLock:
The ReadWriteLock
interface from the java.util.concurrent.locks
package provides separate locks for read and write operations. Multiple threads can hold the read lock simultaneously as long as no thread holds the write lock. This improves concurrency in scenarios where reads are more frequent than writes.
StampedLock:
The StampedLock
class from the java.util.concurrent.locks
package provides a more advanced lock mechanism that supports optimistic read locking. Its useful when you expect reads to be much more common than writes and you want to avoid blocking readers when writers are infrequent.
LockSupport:
The LockSupport
class provides static methods for blocking and unblocking threads at the thread level. Its used for lower-level synchronization operations and is typically used to create custom synchronization constructs.
Condition:
The Condition
interface, also from the java.util.concurrent.locks
package, is used in conjunction with lock objects to allow threads to wait until a specific condition is met. Its often used for more advanced synchronization scenarios.
Semaphore:
The Semaphore
class from the java.util.concurrent
package is a synchronization primitive that allows a fixed number of permits to be acquired, which can help control access to a limited set of resources.
CountDownLatch:
The CountDownLatch
class from the java.util.concurrent
package is a synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
CyclicBarrier:
The CyclicBarrier
class from the java.util.concurrent
package allows a set of threads to wait at a barrier until all participating threads reach that point. Once all threads have reached the barrier, they are released simultaneously.
These are some of the common types of locks and synchronization mechanisms in Java. The choice of lock type depends on the specific concurrency scenario you are dealing with. Its important to understand the characteristics and usage patterns of each type to effectively manage thread synchronization and avoid issues like deadlocks and contention.
there are several types of locks and synchronization mechanisms that you can use to manage thread access to shared resources. Lets explore some of these locks with examples and outputs.
synchronized
Keyword (Intrinsic Lock)javapublic class Counter {
private int value;
public synchronized void increment() {
value++;
}
public synchronized int getValue() {
return value;
}
}
public class CounterThread extends Thread {
private Counter counter;
public CounterThread(Counter counter) {
this.counter = counter;
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
CounterThread thread1 = new CounterThread(counter);
CounterThread thread2 = new CounterThread(counter);
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println("Final value: " + counter.getValue());
}
}
Output:
yamlFinal value: 2000
In this example, the synchronized
keyword is used to acquire and release the intrinsic lock (monitor) associated with the object on which the method is called. This ensures that only one thread can execute the synchronized method at a time, ensuring thread-safety.
ReentrantLock
javaimport java.util.concurrent.locks.*;
public class ReentrantCounter {
private int value;
private Lock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
value++;
} finally {
lock.unlock();
}
}
public int getValue() {
return value;
}
}
public class ReentrantCounterThread extends Thread {
private ReentrantCounter counter;
public ReentrantCounterThread(ReentrantCounter counter) {
this.counter = counter;
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
ReentrantCounter counter = new ReentrantCounter();
ReentrantCounterThread thread1 = new ReentrantCounterThread(counter);
ReentrantCounterThread thread2 = new ReentrantCounterThread(counter);
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println("Final value: " + counter.getValue());
}
}
Output:
yamlFinal value: 2000
In this example, ReentrantLock
is used for explicit locking. It allows a thread to re-enter the same lock multiple times without getting deadlocked. The lock must be released the same number of times it was acquired.
These are just a couple of examples demonstrating different types of locks in Java. Other synchronization mechanisms like ReadWriteLock
, Semaphore
, and Condition
can also be used based on specific concurrency requirements.