Java Reference
In-Depth Information
Explicit Locks
Explicit locking mechanism can be used to coordinate access to shared resources in a multi-threaded environment
without using the keyword
synchronized
. The
Lock
interface, which is declared in the
java.util.concurrent.locks
package, defines the explicit locking operations. The
ReentrantLock
class, in the same package, is the concrete
implementation of the
Lock
interface. The
Lock
interface is declared as follows:
public interface Lock {
void lock();
Condition newCondition();
void lockInterruptibly() throws InterruptedException;
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
void unlock();
}
The use of the
lock()
method to acquire a lock behaves the same as the use of the
synchronized
keyword. The
use of the
synchronized
keyword requires that a thread should acquire and release an object's monitor lock in the
same block of code. When you use the
synchronized
keyword to acquire an object's monitor lock, the lock is released
by the JVM when the program leaves the block in which the lock was acquired. This feature makes working with
intrinsic locks very simple and less error prone. However, in the case of the
Lock
interface, the restriction of acquiring
and releasing of the lock in the same block of code does not apply. This makes it a little flexible to use; however, it is
more error prone because the responsibility of acquiring as well as releasing the lock is on the programmer. It is not
difficult to acquire the lock and forget to release it, resulting in hard-to-find bugs. You must make sure that you release
the lock by calling the
unlock()
method of the
Lock
interface after you are done with the lock. You can use the
lock()
and
unlock()
methods in their simplest form, shown in Listing 6-30. Note the use of a
try-finally
block to release
the lock in the
updateResource()
method. The use of a
try-finally
block is necessary in this case because no matter
how you finish returning from this method after you call
myLock.lock()
, you would like to release the lock. This can
be assured only if you place the call to the
unlock()
method inside the
finally
block.
Listing 6-30.
Using an Explicit Lock in its Simplest Form
// SimpleExplicitLock.java
package com.jdojo.threads;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SimpleExplicitLock {
// Instantiate the lock object
private Lock myLock = new ReentrantLock();
public void updateResource() {
// Acquire the lock
myLock.lock();
try {
// Logic for updating/reading the shared resource goes here
}