Saturday, 16 May 2015

ReentrantLock and Condition in Java

ReentrantLock class in Java as an alternative to synchronized code blocks. ReentrantLocks let you do all the stuff that you can do with synchronized, wait and notify, plus some more stuff besides that may come in handy from time to time.
Condition factors out the Object monitor methods (wait, notify and notifyAll) into distinct objects to give the effect of having multiple wait-sets per object, by combining them with the use of arbitrary Lock implementations. Where a Lock replaces the use of synchronized methods and statements, a Condition replaces the use of the Object monitor methods.

ReentrantLock is unstructured, unlike synchronized constructs -- i.e. you don't need to use a block structure for locking and can even hold a lock across methods. An example:

private ReentrantLock lock;

public void foo() {
  ...
  lock.lock();
  ...
}

public void bar() {
  ...
  lock.unlock();
  ...
}

Note: It is always advisable to write your unlock command in finally. Otherwise if method throw exception after lock method it will never unlock the object.

//****************************************************************
//* Copyright (c) 2015 . All Rights Reserved.
//****************************************************************
package com.java.thread.lock;

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

public class ReentrantLockRunner {
    private int count = 0;
    private Lock lock = new ReentrantLock();
    private Condition cond = lock.newCondition();

    private void increment() {
        for (int i = 0; i < 10000; i++) {
            count++;
        }
    }

    public void firstThread() throws InterruptedException {
        lock.lock();

        System.out.println("Waiting ....");
        cond.await();

        System.out.println("Woken up!");

        try {
            increment();
        } finally {
            lock.unlock();
        }
    }

    public void secondThread() throws InterruptedException {

        Thread.sleep(1000);
        lock.lock();

        System.out.println("Press the return key!");
        new Scanner(System.in).nextLine();
        System.out.println("Got return key!");

        cond.signal();

        try {
            increment();
        } finally {
            System.out.println("Unlocking secondThread()");
            lock.unlock();
        }
    }

    public void finished() {
        System.out.println("Count is: " + count);
    }

    public static void main(final String[] args) throws InterruptedException {

        final ReentrantLockRunner runner = new ReentrantLockRunner();

        final Thread t1 = new Thread(new Runnable() {
            public void run() {
                try {
                    runner.firstThread();
                } catch (final InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });

        final Thread t2 = new Thread(new Runnable() {
            public void run() {
                try {
                    runner.secondThread();
                } catch (final InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });

        t1.start();
        t2.start();

        runner.finished();
    }

}

Output:

Waiting ....
Press the return key!


Got return key!
Unlocking secondThread()
Woken up!



Kindly provide your valuable feedback in comment box.

No comments:

Post a Comment