Thread-related problems

Arithmetic operations on volatile types

Arithmetic operations on volatile types can result in inconsistent values, and represent programming errors in most cases. It is a common misconception that the atomicity guarantee for volatile types as defined in Section 17.7 JLS implies that the field can safely be used for arithmetic calculation, but that's not true. In fact, changes to such a field can get lost, and the value can become inconsistent in terms of business rules. This is known as the lost update problem.

Solution: use synchronization instead.

Severity level: 1

Usage of volatile long and double types

Although the The Java Language Specification guarantees atomic access to volatile long and double field in Section 17.7, many Java VM including the SUN VM including the 1.4.0 releases violated the specification. If you are curious, test your VM.

Solution: Use synchronization, or consider using an int or float.

Severity level: 1

Excessively deep lock nesting

This code segments holds three or more locks at the same time, which is a bad "code smell". In most cases, one lock should be sufficient.

Solution: revisit if you really need that many locks

Severity level: 1

Possible deadlocks because of wrong lock ordering

One of the necessary requirements for a deadlock is that one thread of execution attempts to acquire locks in a different order than another thread. This situation can happen in this class due to the order in which synchronized statements are grouped. This article gives a good overview of this problem.

Solution: correct the order

Severity level: 1

Calls to Object.wait(), notify(), notifyAll() w/o lock

When calling one of the wait(), notify(), or notifyAll() methods, the calling thread must own the lock on the callee, otherwise an exception will occur. Refer to the API documentation of these methods for details.

Solution: wrap the call with a synchronized statement

Severity level: 1

Calls to Object.wait() with more than one lock held

When calling one of the wait() methods the calling threads will be suspended. If it holds other locks during that time, it can block other threads from making progress in the best case, or cause a deadlock in the worst case. Refer to the API documentation of these methods for details.

Solution: revisit why more than lock must be held during the wait() call.

Severity level: 1

Calls to native methods while holding locks

Native methods incur an expensive context switch, especially in Sun's client VM, so it's a good idea to keep them out of synchronized blocks.

Solution: move the call out of the synchronized block, if possible.

Severity level: 2

Inconsistent use of locks when accessing fields

Frequent causes of this kind of error are the broken double-checked locking idiom, or the wrong belief that read access doesn't have to be synchronized. Chapter 18 of the Java Language Specification is the definitive source to understanding the Java Threading model.

Solution: use synchronization each time the field is accessed

Severity level: 3

Using Hashtable in a static field

The class java.util.Hashtable is threadsafe by default. Having an instance in class scope can severely impact scalability in a multi-threaded environment. The same is true for all subclasses of Hashtable, most notably java.util.Properties.

Solution: use a HashMap

Severity level: 2

Objects used for locking that are not declared final

Declaring fields that are used as locks final ensures that accidental reassignments to a such a field is impossible, which would result in concurrent access of a protected path.

Solution: declare the field final

Severity level: 4