Locks and Conditions


J2SE 5.0 introduces a new, more flexible mechanism for obtaining locks on objects. The interface java.util.concurrent.locks.Lock allows you to associate one or more conditions with a lock. Different types of locks exist. For example, the ReadWriteLock implementation allows one thread to write to a shared resource, while allowing multiple threads to read from the same resource. You can also add fairness rules to a reentrant lock to do things like allow threads waiting the longest to obtain the lock first. Refer to the API documentation for details.

The listing of ClockTest shows how you would replace the use of synchronization with the new lock idiom.

 package sis.clock; import java.util.*; import java.util.concurrent.locks.*; import junit.framework.*; public class ClockTest extends TestCase {    private Clock clock;    private Lock lock;    private Condition receivedEnoughTics;    protected void setUp() {       lock = new ReentrantLock();       receivedEnoughTics = lock.newCondition();    }    public void testClock() throws Exception {       final int seconds = 2;       final List<Date> tics = new ArrayList<Date>();       ClockListener listener = createClockListener(tics, seconds);       clock = new Clock(listener);       lock.lock();       try {          receivedEnoughTics.await();       }       finally {          lock.unlock();       }       clock.stop();       verify(tics, seconds);     }    private ClockListener createClockListener(          final List<Date> tics, final int seconds) {       return new ClockListener() {          private int count = 0;          public void update(Date date) {             tics.add(date);             if (++count == seconds) {                lock.lock();                try {                   receivedEnoughTics.signalAll();                }                finally {                   lock.unlock();                }             }          }       };    }    ... } 

The modified and slightly refactored implementation of ClockTest uses a ReentrantLock implementation of the Lock interface. A thread interested in accessing a shared resource sends the message lock to a ReentrantLock object. Once the thread obtains the lock, other threads attempt to lock the block until the first thread releases the lock. A thread releases the lock by sending unlock to a Lock object. You should always ensure an unlock occurs by using a try-finally block.

The shared resource in ClockTest is the Condition object. You obtain a Condition object from a Lock by sending it the message newCondition (see the setUp method). Once you have a Condition object, you can block on it by using await. As with the wait method, code in await releases the lock and suspends the current thread.[12] Code in another thread signals that the condition has been met by sending the Condition object the message signal or signalAll.

[12] Which suggests you may not need to enclose an await call in a TRy-finally block. Don't risk ityou can't guarantee that something won't go awry with the code in await.

Coupled with the use of Condition objects, the idiom shown in ClockTest effectively replaces the classic wait/notify scheme.



Agile Java. Crafting Code with Test-Driven Development
Agile Javaв„ў: Crafting Code with Test-Driven Development
ISBN: 0131482394
EAN: 2147483647
Year: 2003
Pages: 391
Authors: Jeff Langr

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net