The JavaTM Tutorial
Previous Page Lesson Contents Next Page Start of Tutorial > Start of Trail > Start of Lesson Search
Feedback Form

Trail: Essential Java Classes
Lesson: Threads: Doing Two or More Tasks at Once

Explicit Locks and Condition Variables

Another way to ensure exclusive access to a section of code is to use an explicit lock. An explicit lock is more flexible than using the synchronized keyword because the lock can span a few statements in a method or multiple methods in addition to the scopes (block and method) supported by synchronized.

To create an explicit lock, instantiate an implementation of the Lock interface, usually ReentrantLock. To grab the lock, invoke the lock method; to release the lock you invoke the unlock method. Since the lock is not automatically released when the method exits, you should wrap the lock and unlock methods in a try/finally clause.

To wait on an explicit lock, create a condition variable (an object that supports the Condition interface) using the Lock.newCondition method. Condition variables provide the methods await — to wait for the condition to be true, and signal and signalAll — to notify all waiting threads that the condition has occurred. Like the Object.wait method, Condition.await has several variants, which are listed in the next table.

Condition.await Methods
Method Description
await Waits for a condition to occur.
awaitInterruptibly Waits for a condition to occur; cannot be interrupted.
awaitNanos(long timeout) Waits for a condition to occur. If the notification does not occur before a timeout specified in nanoseconds, it returns.
await(long timeout, TimeUnit unit) Waits for a condition to occur. If the notification does not occur before a timeout specified in the provided time unit, it returns.
await(Date timeout) Waits for a condition to occur. If the notification does not occur before the specified time, it returns.
In the following example, CubbyHole has been rewritten to use an explicit lock and condition variable. To run this version of the producer-consumer example, execute ProducerConsumerTest2.
import java.util.concurrent.locks.*;
public class CubbyHole2 {
    private int contents;
    private boolean available = false;
    private Lock aLock = new ReentrantLock();
    private Condition condVar = aLock.newCondition();

    public int get(int who) {
        aLock.lock();
        try {
            while (available == false) {
                try {
                    condVar.await();
                } catch (InterruptedException e) { }
            }
            available = false;
            System.out.format("Consumer %d got: %d%n", who, contents);
            condVar.signalAll();
        } finally {
            aLock.unlock();
        }
        return contents;
    }

    public void put(int who, int value) {
        aLock.lock();
        try {
            while (available == true) {
                try {
                    condVar.await();
                } catch (InterruptedException e) { }
            }
            contents = value;
            available = true;
            System.out.format("Producer %d put: %d%n", who, contents);
            condVar.signalAll();
        } finally {
            aLock.unlock();
        }
    }
}

Previous Page Lesson Contents Next Page Start of Tutorial > Start of Trail > Start of Lesson Search
Feedback Form

Copyright 1995-2005 Sun Microsystems, Inc. All rights reserved.