The keyword synchronized
is known to make sure the synchronization of threads within a process in Java. However, care should be taken when writing a thread-safe class to defend itself from possible denial-of-service attack
[Effective Java].
A idiom called private lock object can be used to prevent the DOS attack. By calling the synchronized
block, the caller is only able to obtain a lock object in the instance, not the whole instance itself so that other threads may still proceed. This technique also enhance concurrency granularity as different locks can be created according to the program logic and resources.
Internal object for locking is especially suitable in a inheritance environment. If the superclass use the entire instance for locking, a subclass can interfere with its operation. Declare lock as member variable eliminate this situation.
Noncompliant Code Example
A malicious client using the instantiated thread-safe object can mount a denial-of-service attack simply by holding the lock on the object:
class importantObj { public synchronized void changeValue() { // lock on this ... } ... } // Denial-of-service attack from caller synchronized (importantObject) { Thread.sleep(Integer.MAX_VALUE); // Disable importantObject }
Compliant Solution
// private lock object idiom - thawts denial-of-service attack class importantObj { private Object lock = new Object(); public void changeValue() { // lock on this synchronized(lock) { ... } } ... }
If the method changeValue
is called in this case, the lock is obtained on a private Object
that is both invisible and inaccessible from the caller. The this
instance is not vulnerable from denial-of-service attack. Thread-safe class may be protected in this way by using the private lock object idiom.