|
|
Home
Synchronization and concurrency
wait/notify
final
volatile
synchronized keyword
Java threading
Deadlock (and avoiding it)
Java 5: ConcurrentHashMap
Atomic variables
Explicit locks
Queues
Semaphores
CountDownLatch
CyclicBarrier
Explicit locks in Java 5Before Java 5, the language offered two key synchronization facilities: the synchronized keyword allows exclusive locking at the level of a block or method, and in tandem with this locking mechanism, the wait/notify idiom effectively allows threads to wait, interruptably, for a 'signal' from another thread. The standard form of locking provided by the synchronized keyword has limitations:
Of course, it does have the advantage of simple syntax and built-in support from the JVM (people who have stuck to good-old synchronized have seen their tenacity rewarded with gradual performance improvements over the course of several JVM updates). If you need some of the features of the above list, you can 'roll your own' lock with judicious use of wait/notify (for example, some of the Swing text editing code actually uses an implementation of a read/write lock). So we could create a Lock class with the following functionality:
public class Lock {
/**
* Waits for up to 'maxWait' milliseconds to acquire the lock,
* and returns true if the lock was acquired.
**/
public boolean acquireLock(int maxWait)
throws InterruptedException { ... }
public void releaseLock() { ... }
}
(By the way, if you're wondering how to actually implement the lock we've just described, then see this rough implementation of a lock pre-Java 5.) Such a lock would then be used by the caller as follows:
Lock lck = getDatabaseLock();
if (!lck.acquireLock(2000)) {
throw new RuntimeException("Couldn't get DB lock in 2 seconds");
}
try {
... do interesting thing with database ...
} finally {
lck.releaseLock();
}
One disadvantage of this locking mechanism (apart from any performance issues2) is the syntax: we have to explicitly deal with lock objects and in particular, we must ensure that we release the lock in a finally clause once we've acquired it. With a regular synchronized block, the compiler takes care of this automatically for us. But on the plus side, this lock solves some of the problems mentioned above. In particular, it won't wait forever if the lock can't be acquired for some reason. And once our lock is implemented in Java, we can do other interesting things with it, such as build in performance monitoring. Locks in Java 5Well, all this introduction wasn't intended to make you run away and write a new lock class. Java 5 already introduces classes with functionality similar to the example Lock class above. But they call on the new atomic variable access facilities of Java 5 to create more efficient, scalable versions than were previously possible. They are also fuller implementations, dealing with some issues (in particular fairness) which we don't attempt to deal with in our simple example. So, on the next page, we look at explicit lock classes in Java 5.
1. There is a bad way: you could set which object gets synchronized on at runtime,
and to mean "don't synchronize", you can synchronize on new Object(). Article written by Neil Coffey (@BitterCoffey). Software
Copyright © Neil Coffey 2013. All rights reserved. |