Instances of classes that implement either or both of the Lock
and Condition
interfaces of the java.util.concurrent.locks
package are known as high-level concurrency objects. Using the intrinsic locks of such objects is a questionable practice even in cases where the code may appear to function correctly. Consequently, programs that interact with such objects must use only the high-level locking facilities provided by the interfaces; use of the intrinsic locks is prohibited. This problem generally arises when code is refactored from intrinsic locking to the java.util.concurrent
dynamic-locking utilities.
Noncompliant Code Example (ReentrantLock
)
The doSomething()
method in this noncompliant code example synchronizes on the intrinsic lock of an instance of ReentrantLock
rather than on the reentrant mutual exclusion Lock
encapsulated by ReentrantLock
.
private final Lock lock = new ReentrantLock(); public void doSomething() { synchronized(lock) { // ... } }
Compliant Solution (lock()
and unlock()
)
This compliant solution uses the lock()
and unlock()
methods provided by the Lock
interface.
private final Lock lock = new ReentrantLock(); public void doSomething() { lock.lock(); try { // ... } finally { lock.unlock(); } }
In the absence of a requirement for the advanced functionality of the java.util.concurrent
package's dynamic-locking utilities, it is better to use the Executor
framework or other concurrency primitives such as synchronization and atomic classes.
Risk Assessment
Synchronizing on the intrinsic lock of high-level concurrency utilities can cause nondeterministic behavior resulting from inconsistent locking policies.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
LCK03-J |
medium |
probable |
medium |
P8 |
L2 |
Bibliography
[API 2006] |
|
|
|
Synchronization |
|
Locking |
|