Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Wiki Markup
Code that uses synchronization can sometimes be enigmatic and tricky to debug. Misuse of synchronization primitives is a common source of implementation errors. TheAn analysis of the JDK 1.6.0 source code unveiled at least 31 bugs that fell into this category. \[[Pugh 08|AA. Java References#Pugh 08]\]

...

Wiki Markup
A {{String}} constant is interned in Java. According to the Java API \[[API 06|AA. Java References#API 06]\] Class {{String}} documentation:

...

Consequently, a String constant behaves like a global variable in the JVM. As demonstrated in this noncompliant code example, even if each instance of an object maintains its own field lock, it points to a common String constant in the JVM. Legitimate code that locks on the same String constant will render renders all synchronization attempts inadequate. Likewise, hostile code from any other package can deliberately exploit this vulnerability.

Code Block
bgColor#FFcccc
// thisThis bug was found in jetty-6.1.3 BoundedThreadPool
private final String _lock = "one";
synchronized(_lock) { /* ... */ }

...

Code Block
int lock = 0;
Integer Lock = lock; // boxedBoxed primitive Lock will be shared

...

Code Block
bgColor#FFcccc
private Boolean initialized = Boolean.FALSE;
synchronized(initialized) { 
  if (!initialized) {
    // performPerform initialization
    initialized = Boolean.TRUE;
  }
}

...

Note that the instance of the raw object should not be changed from within the synchronized block. For example, creating and storing the reference of a new object into the lock field is highly inadvisable. To prevent such modifications, declare the lock field final.

...

This does not mean that it is required to synchronize on the Class object of the base class.

Compliant Solution

Explicitly define the name of the class (superclass in this example) in the synchronization block. This can be achieved in two ways. One way is to explicitly pass the superclass's instance.

...

Code Block
bgColor#FFcccc
Map<Integer, String> m = Collections.synchronizedMap(new HashMap<Integer, String>());
Set<Integer> s = m.keySet();
synchronized(s) {  // Incorrectly synchronizes on s
  for(Integer k : s) { 
    //* doDo something 
 */ }
}

Compliant Solution

This compliant solution correctly synchronizes on the Collection object instead of the Collection view.

Code Block
bgColor#ccccff
// ...
synchronized(m) {  // Synchronize on m, not s
  for(Integer k : s) { 
    //* doDo something  
 */ }
}

Noncompliant Code Example

...

Code Block
bgColor#FFcccc
final Lock lock = new ReentrantLock();
synchronized(lock) { /* do something... */ }

Compliant Solution

The proper mechanism to lock in this case is to explicitly use the lock() and unlock() methods provided by the ReentrantLock class.

...