Monday, September 22, 2014

ReentrantLock Introduction

Lock provides a tool to control access to a shared resource in a multi-threaded environment. A lock provides access to only one thread at a time to the shared resource. Using synchronized methods and statements provides access to an implicit lock for an object. However in certain scenarios we might need access explicitly to the lock object for flexibility. ReentrantLock is a mutual exclusion lock similar to implicit lock provided by synchronized methods and statements but with additional flexibility. 

Java ReentrantLock

Java supports Lock interface in the package java.util.concurrent.locks. ReentrantLock implements the Lock interface and provides the re-entrant mutual exclusive lock. Some of the key APIs of ReentrantLock are listed below.

  • ReentrantLock() - Creates ReentrantLock instance.
  • void lock() - Acquires the lock.
  • void unlock() - Releases the lock.
  • boolean tryLock() - Acquires the lock only if the lock is not held by another thread.
  • boolean isLocked() - Checks if lock is held by another thread.

Java ReentrantLock Example

In this example we have a producer and consumer task using a ReentrantLock object to protect a shared resource. 

package com.sourcetricks.locks;

import java.util.concurrent.locks.ReentrantLock;

public class JavaLocksDemo {

    // Shared resources to be guarded
    private static int count = 0;
    
    // Producer thread. Counts up the resource.
    private static class ProducerTask implements Runnable {

      private ReentrantLock lock = null;
      
      ProducerTask(ReentrantLock lock) {
        this.lock = lock;
      }
      
      @Override
      public void run() {       
          System.out.println("Producer requesting lock");
          lock.lock();
          System.out.println("Producer gets lock");
          for ( int i = 0; i < 5; i++ ) {
            count = count + 1;
            System.out.println("Counting up");
          }
          try {
            Thread.sleep(5000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
          System.out.println("Producer releases lock");
          lock.unlock();
      }
      
    }
    
    // Consumer thread. Counts down the resource.
    private static class ConsumerTask implements Runnable {

      private ReentrantLock lock = null;
      
      ConsumerTask(ReentrantLock lock) {
        this.lock = lock;
      }
      
      @Override
      public void run() {
          System.out.println("Consumer requesting lock");
          lock.tryLock();
          System.out.println("Consumer gets lock");
          for ( int i = 0; i < 5; i++ ) {
            count = count - 1;
            System.out.println("Counting down");
          }
          System.out.println("Consumer releases lock");         
          lock.unlock();
      }    
    }
    
  public static void main(String[] args) {
    ReentrantLock lock = new ReentrantLock();
    Thread producer = new Thread(new ProducerTask(lock));
    Thread consumer = new Thread(new ConsumerTask(lock));
    producer.start();
    consumer.start();
  }
}

This program produces the following output.

Producer requesting lock
Consumer requesting lock
Producer gets lock
Counting up
Counting up
Counting up
Counting up
Counting up
Producer releases lock
Consumer gets lock
Counting down
Counting down
Counting down
Counting down
Counting down
Consumer releases lock

Refer to Java Tutorials page for more tutorials.

0 comments :

Post a Comment

Contact Form

Name

Email *

Message *

Back to Top