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
.
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 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 | |
9 Comments
Robert Seacord (Manager)
I'm having a hard time finding the Bill Pugh powerpoint presentation on the JavaOne website.
Dhruv Mohindra
The presentations before 2009 seem to have vanished into thin air. I can't find any archives.
Masaki Kubo
What do you mean by "high-level" concurrency objects as is written in the title? I couldn't get the idea after reading this guideline. This guideline will not apply to non high-level objects(if there's any)? It would be better to rephrase it if appropriate.
Dean Sutherland
I expected this to be clear based on the opening sentence: "Programs must not lock on an object of a class that implements either or both of the Lock and Condition interfaces of the java.util.concurrent.locks package." Objects of classes that implement either or both of the Lock and Condition interfaces of the java.util.concurrent.locks package are the "high-level concurrency objects" referred to by the title. I'll re-write to clarify... ...and the rewrite is now done.
Masaki Kubo
Thanks Dean!
James Ahlborn
A minor point, but in the last sentence: "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 theExecutor
framework or other concurrency primitives such as synchronization and atomic classes." I fail to see how the "Executor framework" is a useful alternative locking utility?David Svoboda
Agreed. I removed the reference to Executor.
Vipin Sharma
Hi Dhruv, from your example I can understand what kind of situation can cause problem but Its not clear why it will create a problem. Can you please provide example for below sentence.
"This problem generally arises when code is refactored from intrinsic locking to the
java.util.concurrent
dynamic-locking utilities."David Svoboda
I expanded the intro text to answer your question.