Concepts of Programming Languages

(Sean Pound) #1

612 Chapter 13 Concurrency


13.7.6 Nonblocking Synchronization


Java includes some classes for controlling accesses to certain variables that do
not include blocking or waiting. The java.util.concurrent.atomic
package defines classes that allow certain nonblocking synchronized access to
int, long, and boolean primitive type variables, as well as references and
arrays. For example, the AtomicInteger class defines getter and setter meth-
ods, as well as methods for add, increment, and decrement operations. These
operations are all atomic; that is, they cannot be interrupted, so locks are not
required to guarantee the integrity of the values of the affected variables in a
multithreaded program. This is fine-grained synchronization—just a single
variable. Most machines now have atomic instructions for these operations on
int and long types, so they are often easy to implement (implicit locks are
not required).
The advantage of nonblocking synchronization is efficiency. A nonblock-
ing access that does not occur during contention will be no slower, and usually
faster than one that uses synchronized. A nonblocking access that occurs
during contention definitely will be faster than one that uses synchronized,
because the latter will require suspension and rescheduling of threads.

13.7.7 Explicit Locks


Java 5.0 introduced explicit locks as an alternative to synchronized method
and blocks, which provide implicit locks. The Lock interface declares the
lock, unlock, and tryLock methods. The predefined ReentrantLock class
implements the Lock interface. To lock a block of code, the following idiom
can be used:

Lock lock = new ReentrantLock();

...
Lock.lock();
try {
// The code that accesses the shared data
} finally {
Lock.unlock();
}


This skeletal code creates a Lock object and calls the lock method on the
Lock object. Then, it uses a try block to enclose the critical code. The call to
unlock is in a finally clause to guarantee the lock is released, regardless of
what happens in the try block.
There are at least two situations in which explicit locks are used rather
than implicit locks: First, if the application needs to try to acquire a lock but
cannot wait forever for it, the Lock interface includes a method, tryLock, that
takes a time limit parameter. If the lock is not acquired within the time limit,
execution continues at the statement following the call to tryLock. Second,
Free download pdf