Multithreading Revealed Part 3: Types of Locks for Multithreading in Java

Multithreading Revealed Part 3: Types of Locks for Multithreading in Java

In multithreading, locks are essential to ensure that only one thread accesses a critical section of code at a time, preventing data corruption and ensuring thread safety. Java provides several types of locks with different features and use cases. Understanding these locks helps you choose the right one for your specific scenario.

1. Intrinsic Locks (Monitor Locks)

Every object in Java has an intrinsic lock (also known as a monitor lock) associated with it. When a thread enters a synchronized method or block, it acquires the intrinsic lock for that object.

  • Synchronized Method:

public synchronized void synchronizedMethod() {
      // Critical section
  }        

  • Synchronized Block:

 public void method() {
      synchronized(this) {
          // Critical section
      }
  }        

Intrinsic locks are simple to use but come with limitations, such as no timed lock waits or interruptible lock waits.

2. ReentrantLock

ReentrantLock is part of the java.util.concurrent.locks package and provides more advanced locking features compared to intrinsic locks. It allows a thread to re-acquire the lock if it already holds it, hence the term reentrant.

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

  public class ReentrantLockExample {

      private final Lock lock = new ReentrantLock();

      public void performTask() {
          lock.lock();
          try {
              // Critical section
          } finally {
              lock.unlock();
          }
      }

  }        

3. ReentrantReadWriteLock

ReentrantReadWriteLock improves performance in scenarios where read operations are more frequent than write operations. It provides separate locks for reading and writing, allowing multiple threads to read simultaneously while ensuring exclusive access for write operations.

import java.util.concurrent.locks.ReentrantReadWriteLock;

  public class ReentrantReadWriteLockExample {

      private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
      private final ReentrantReadWriteLock.ReadLock readLock = rwLock.readLock();
      private final ReentrantReadWriteLock.WriteLock writeLock = rwLock.writeLock();

      private int data;
      public void writeData(int value) {

          writeLock.lock();

          try {
              data = value;
          } finally {
              writeLock.unlock();
          }

      }

      public int readData() {
          readLock.lock();
          try {
              return data;
          } finally {
              readLock.unlock();
          }
      }

  }        

4. Semaphore

A Semaphore controls access to a resource that allows multiple permits, limiting the number of concurrent accesses.

import java.util.concurrent.Semaphore;

  public class SemaphoreExample {

      private final Semaphore semaphore = new Semaphore(3);

      public void accessResource() {

          try {
              semaphore.acquire();
              // Access resource
          } catch (InterruptedException e) {
              e.printStackTrace();
          } finally {
              semaphore.release();
          }

      }
  }        

Semaphores are useful when you need to limit the number of threads accessing a particular resource.

Conclusion

Java offers a variety of locks to handle different multithreading scenarios, from simple intrinsic locks to more advanced ReentrantLock, ReentrantReadWriteLock, and Semaphore. Understanding these locks and their use cases can help you design more efficient and thread-safe applications.


Stay connected on LinkedIn for more articles on Java and other programming topics. Feel free to share your experiences, ask questions, and contribute to the discussion.

要查看或添加评论,请登录

Saksham Kapoor的更多文章

社区洞察

其他会员也浏览了