...
This noncompliant code example synchronizes on a Boolean
lock object.
Code Block | ||
---|---|---|
| ||
private final Boolean initialized = Boolean.FALSE;
public void doSomething() {
synchronized (initialized) {
// ...
}
}
|
...
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.
...
This noncompliant code example locks on an interned String
object.
Code Block | ||
---|---|---|
| ||
private final String lock = new String("LOCK").intern();
public void doSomething() {
synchronized (lock) {
// ...
}
}
|
According to the Java API class {{ Wiki Markup java.lang.String
}} documentation \ [[API 2006|AA. Bibliography#API 06]\]:
When the
intern()
method is invoked, if the pool already contains a string equal to thisString
object as determined by theequals(Object)
method, then the string from the pool is returned. Otherwise, thisString
object is added to the pool and a reference to thisString
object is returned.
...
This noncompliant code example locks on a final String
literal.
Code Block | ||
---|---|---|
| ||
// This bug was found in jetty-6.1.3 BoundedThreadPool
private final String lock = "LOCK";
public void doSomething() {
synchronized (lock) {
// ...
}
}
|
...
This compliant solution locks on a noninterned String
instance.
Code Block | ||
---|---|---|
| ||
private final String lock = new String("LOCK");
public void doSomething() {
synchronized (lock) {
// ...
}
}
|
...
This compliant solution synchronizes on a private final lock object. This is one of the few cases in which a java.lang.Object
instance is useful.
Code Block | ||
---|---|---|
| ||
private final Object lock = new Object();
public void doSomething() {
synchronized (lock) {
// ...
}
}
|
...
A significant number of concurrency vulnerabilities arise from locking on the wrong kind of object. It is important to consider the properties of the lock object rather than simply scavenging for objects on which to synchronize.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
LCK01-J | medium | probable | medium | P8 | L2 |
Automated Detection
Some static analysis tools can detect violations of this rule.
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
The Checker Framework |
| Lock Checker | Concurrency and lock errors (see Chapter 6) | ||||||
Parasoft Jtest |
| CERT. |
...
LCK01.SCS | Do not synchronize on constant Strings | ||||||||
PVS-Studio |
| V6070 | |||||||
SonarQube |
| S1860 | |||||||
ThreadSafe |
| CCE_CC_REUSEDOBJ_SYNC | Implemented |
Bibliography
[API 2006] | Class String, Collections |
Locking | |
Synchronization | |
...
Bibliography
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="7e855143-16f6-4b9d-84e1-7ca23bd03000"><ac:plain-text-body><![CDATA[ | [[API 2006 | AA. Bibliography#API 06]] | Class String, Collections | ]]></ac:plain-text-body></ac:structured-macro> | |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="afbb956b-1bf1-4e62-a9a6-d309f6c86d93"><ac:plain-text-body><![CDATA[ | [[Findbugs 2008 | AA. Bibliography#Findbugs 08]] |
| ]]></ac:plain-text-body></ac:structured-macro> | |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="6b30f077-e87b-458a-a9c5-5b01279f2b69"><ac:plain-text-body><![CDATA[ | [[Miller 2009 | AA. Bibliography#Miller 09]] | Locking | ]]></ac:plain-text-body></ac:structured-macro> | |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="0df14247-32f0-46d4-a05a-892210377ac0"><ac:plain-text-body><![CDATA[ | [[Pugh 2008 | AA. Bibliography#Pugh 08]] | Synchronization | ]]></ac:plain-text-body></ac:structured-macro> | |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="1577d377-ceb9-4092-851d-fd1f4bfe10ce"><ac:plain-text-body><![CDATA[ | [[Tutorials 2008 | AA. Bibliography#Tutorials 08]] | [Wrapper Implementations | http://java.sun.com/docs/books/tutorial/collections/implementations/wrapper.html] | ]]></ac:plain-text-body></ac:structured-macro> |