...
This noncompliant code example locks on a boxed Integer
object.
Code Block | ||
---|---|---|
| ||
private int lockcount = 0; private final Integer Lock = lockcount; // Boxed primitive Lock is shared public void doSomething() { synchronized (Lock) { count++; // ... } } |
Boxed types may use the same instance for a range of integer values; consequently, they suffer from the same reuse problem as Boolean
constants. The wrapper object are reused when the value can be represented as a byte; JVM implementations are also permitted to reuse wrapper objects for larger ranges of values. While use of the intrinsic lock associated with the boxed Integer
wrapper object is insecure; instances of the Integer
object constructed using the new
operator (new Integer(value)
) are unique and not reused. In general, locks on any data type that contains a boxed value are insecure.
...
This compliant solution locks on a nonboxed Integer
, using a variant of the private lock object idiom. The doSomething()
method synchronizes using the intrinsic lock of the Integer
instance, Lock
.
Code Block | ||
---|---|---|
| ||
private int lockcount = 0; private final Integer Lock = new Integer(lockcount); public void doSomething() { synchronized (Lock) { count++; // ... } } |
When explicitly constructed, an Integer
object has a unique reference and its own intrinsic lock that is distinct not only from other Integer
objects, but also from boxed integers that have the same value. While this is an acceptable solution, it can cause maintenance problems because developers can incorrectly assume that boxed integers are also appropriate lock objects. A more appropriate solution is to synchronize on a private final lock object as described in the final compliant solution for this rule.
...