Java Thread Tutorial - Java Explicit Locks








Explicit locking mechanism can be used to coordinate access to shared resources in a multi-threaded environment.

The Lock interface, which is declared in the java.util.concurrent.locks package, defines the explicit locking operations.

The ReentrantLock class, in the same package, is the concrete implementation of the Lock interface.

The Lock interface is declared as follows:

public interface Lock {
  void lock();

  Condition newCondition();

  void lockInterruptibly() throws InterruptedException;

  boolean tryLock();

  boolean tryLock(long time, TimeUnit unit) throws InterruptedException;

  void unlock();
}

lock() method acquires a lock behaves the same as the use of the synchronized keyword.

We must release the lock by calling the unlock() method of the Lock interface after we are done with the lock.

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/*from w w  w.j  a v a  2s.c  om*/
public class Main {
  // Instantiate the lock object
  private Lock myLock = new ReentrantLock();

  public void updateResource() {

    try {
      // Acquire the lock
      myLock.lock();
    } finally {
      // Release the lock
      myLock.unlock();
    }
  }
}




Example

The following code models the philosophers assuming that an object of the ReentrantLock class represents a fork.

import java.util.concurrent.locks.Lock;
/*www .  j a v  a  2s .  co  m*/
class Philosopher {
  private Lock leftFork;
  private Lock rightFork;
  private String name; // Philosopher's name

  public Philosopher(Lock leftFork, Lock rightFork, String name) {
    this.leftFork = leftFork;
    this.rightFork = rightFork;
    this.name = name;
  }

  public void think() {
    System.out.println(name + "  is thinking...");
  }

  public void eat() {
    if (leftFork.tryLock()) {
      try {
        if (rightFork.tryLock()) {
          try {
            System.out.println(name + "  is eating...");
          } finally {
            rightFork.unlock();
          }
        }
      } finally {
        leftFork.unlock();
      }
    }
  }
}




Example 2

A ReentrantReadWriteLock class is an implementation of the ReadWriteLock Interface. Only one thread can hold the write lock of ReentrantReadWriteLock, whereas multiple threads can hold its read lock.

The following code demonstrates the usage of ReentrantReadWriteLock.

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/*  ww w  . j  a v  a2  s . c o  m*/
public class Main {
  private int value;
  private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
  private Lock rLock = rwLock.readLock();
  private Lock wLock = rwLock.writeLock();

  public Main(int value) {
    this.value = value;
  }

  public int getValue() {
    rLock.lock();
    try {
      return this.value;
    } finally {
      rLock.unlock();
    }
  }

  public void setValue(int value) {
    wLock.lock();
    try {
      this.value = value;
    } finally {
      wLock.unlock();
    }
  }
}