Compound operations are operations that consist of more than one discrete operation. Expressions that include postfix or prefix increment ({{\Wiki Markup +\+}}), postfix or prefix decrement ({{\-\-}}), or compound assignment operators always result in compound operations. Compound assignment expressions use operators such as {{\*=, /=, %=, \ +=, \ -=, <<=, >>=, >>>=, \ ^=}} and {{\|=}} \ [[JLS 2005|AA. References#JLS 05]\]. Compound operations on shared variables must be performed atomically to prevent [data races|BB. Glossary#data race] and [race conditions|BB. Glossary#race conditions]. and race conditions.
For information about the atomicity of a grouping of calls to independently atomic methods that belong to thread-safe classes, see rule VNA03-J. Do not assume that a group of calls to independently atomic methods is atomic.
...
| Code Block | ||
|---|---|---|
| ||
final class Flag {
private volatile boolean flag = true;
public synchronized void toggle() {
flag ^= true; // Same as flag = !flag;
}
public boolean getFlag() {
return flag;
}
}
|
...
This approach must not be used for getter methods that perform any additional operations other than returning the value of a volatile field without use of synchronization. Unless read performance is critical, this technique may lack significant advantages over synchronization \[ [Goetz 2006|AA. References#Goetz 06]\].
Compliant Solution (Read-Write Lock)
...
| Code Block | ||
|---|---|---|
| ||
final class Flag {
private boolean flag = true;
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final Lock readLock = lock.readLock();
private final Lock writeLock = lock.writeLock();
public void toggle() {
writeLock.lock();
try {
flag ^= true; // Same as flag = !flag;
} finally {
writeLock.unlock();
}
}
public boolean getFlag() {
readLock.lock();
try {
return flag;
} finally {
readLock.unlock();
}
}
}
|
...
Read-write locks allow shared state to be accessed by multiple readers or a single writer but never both. According to Goetz \ [[Goetz 2006|AA. References#Goetz 06]\]
In practice, read-write locks can improve performance for frequently accessed read-mostly data structures on multiprocessor systems; under other conditions they perform slightly worse than exclusive locks due to their greater complexity.
...
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
|---|---|---|---|---|---|
VNA02-J | medium | probable | medium | P8 | L2 |
Automated Detection
Some available static analysis tools can detect the instances of nonatomic update of a concurrently shared value. The result of the update is determined by the interleaving of thread execution. These tools can detect the instances where thread-shared data is accessed without holding an appropriate lock, possibly causing a race condition.
...
CWE-667. Improper locking | |
| CWE-413. Improper resource locking |
| CWE-366. Race condition within a thread |
| CWE-567. Unsynchronized access to shared data in a multithreaded context |
Bibliography
...
[[API 2006] | AA. References#API 06]] | Class | ]]></ac:plain-text-body></ac:structured-macro> | ||||
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="640f96f1-baa5-43a9-91df-2a70699206fc"><ac:plain-text-body><![CDATA[ | [[Bloch 2008 | AA. References#Bloch 08]] | Item 66. Synchronize access to shared mutable data | ]]></ac:plain-text-body></ac:structured-macro> | |||
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="a52fac7b-c54b-4af8-bca9-65cca0e41b60"><ac:plain-text-body><![CDATA[ | [[Goetz 2006 | AA. References#Goetz 06]] | 2.3, Locking | ]]></ac:plain-text-body></ac:structured-macro> | |||
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="c8583ee6-f507-4866-97fc-a3e7b000d919"><ac:plain-text-body><![CDATA[ | [[JLS 2005 | AA. References#JLS 05]] | [Chapter 17, Threads and Locks | http://java.sun.com/docs/books/jls/third_edition/html/memory.html] ]]></ac:plain-text-body></ac:structured-macro> | |||
| §17.4.5, Happens-Before Order | ||||||
Class | |||||||
Item 66. Synchronize access to shared mutable data | |||||||
2.3, Locking | |||||||
[JLS 2005] |
| §17.4.3, Programs and Program Order | |||||
| §17.4.8, Executions and Causality Requirements 5, Happens-Before Order | ||||||
| §17.4.3, Programs and Program Order | ||||||
| §17.4.8, Executions and Causality Requirements | ||||||
[Lea 2000] | <ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="44bf7463-35ec-43b5-a9a9-26ab6ee21312"><ac:plain-text-body><![CDATA[ | [[Lea 2000 | AA. References#Lea 00]] | Section 2.2.7, The Java Memory Model ]]></ac:plain-text-body></ac:structured-macro>Memory Model | |||
| Section 2.1.1.1, Objects and Locks Objects and Locks | ||||||
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="f5dcd797-618c-422d-9694-169eaccd54d7"><ac:plain-text-body><![CDATA[ | [[Tutorials 2008 | AA. References#Tutorials 08]] | [Java Concurrency Tutorial | http://java.sun.com/docs/books/tutorial/essential/concurrency/index.html] | ]]></ac:plain-text-body></ac:structured-macro> |
...