...
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. Code that uses the intrinsic lock of a Lock
object is likely to interact with code that uses the Lock
interface. These two components will believe they are protecting data with the same lock, while they are, in fact, using two distinct locks. As such, the Lock
will fail to protect any data.
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
.
Code Block | ||
---|---|---|
| ||
}}. Using intrinsic locks of these classes is a questionable practice even though the code may appear to function correctly. This problem is commonly uncovered when code is refactored from intrinsic locking to the {{java.util.concurrent}} dynamic locking utilities. h2. Noncompliant Code Example ({{ReentrantLock}} lock object) The {{doSomething()}} method in this noncompliant code example synchronizes on the the intrinsic lock of an instance of {{ReentrantLock}} instead of the reentrant mutual exclusion {{Lock}} encapsulated by {{ReentrantLock}}. {code:bgColor=#FFcccc} private final Lock lock = new ReentrantLock(); public void doSomething() { synchronized(lock) { // ... } } {code} h2. Compliant Solution ({{ |
Compliant Solution (lock()
...
and
...
unlock()
)
This compliant solution uses the lock()
and unlock()
methods provided by the Lock
interface.
Code Block | ||
---|---|---|
| ||
}}) Instead of using the intrinsic locks of objects that implement the {{Lock}} interface, such as {{ReentrantLock}}, use the {{lock()}} and {{unlock()}} methods provided by the {{Lock}} interface. {code:bgColor=#ccccff} private final Lock lock = new ReentrantLock(); public void doSomething() { lock.lock(); try { // ... } finally { lock.unlock(); } } {code} If there is no requirement for using the advanced functionality of the dynamic locking utilities of package {{ |
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 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 |
Automated Detection
Bibliography
[API 2006] | |
Synchronization | |
Locking | |
...