...
The Java Language Specification also permits reads and writes of 64-bit values to be nonatomic although this is not an issue with most modern JVMs (see CON25-J. Ensure atomicity when reading and writing 64-bit values).
Noncompliant Code Example (decrement)
In this noncompliant code example, the field itemsInInventory
can be accessed by multiple threads.
Code Block | ||
---|---|---|
| ||
private int itemsInInventory = 100;
public int removeItem() {
if (itemsInInventory > 0) {
return itemsInInventory--; // Returns new count of items in inventory
}
return -1; // Error code
}
|
...
Code Block | ||
---|---|---|
| ||
private volatile int itemsInInventory = 100;
public int removeItem() {
if (itemsInInventory > 0) {
return itemsInInventory--; // Returns new count of items in inventory
}
return -1; // Error code
}
|
...
Code Block | ||
---|---|---|
| ||
private int itemsInInventory = 100;
public synchronized int removeItem() {
if (itemsInInventory > 0) {
return itemsInInventory--; // Returns new count of items in inventory
}
return -1; // Error Code
}
|
...
Code Block | ||
---|---|---|
| ||
private int itemsInInventory = 100;
public int removeItem() {
synchronized(this) {
if (itemsInInventory > 0) {
return itemsInInventory--; // Returns new count of items in inventory
}
return -1; // Error code
}
}
|
...
Code Block | ||
---|---|---|
| ||
public class Sync {
private int itemsInInventory = 100;
private final Lock lock = new ReentrantLock();
public int removeItem() {
Boolean myLock = false;
try {
myLock = lock.tryLock();
if (itemsInInventory > 0) {
return itemsInInventory--;
}
} finally {
if (myLock) {
lock.unlock();
}
}
return -1; // Error code
}
}
|
Code that uses this lock behaves similar to synchronized code that uses the traditional monitor lock. In addition, it provides several other capabilities, for instance, the tryLock()
method does not block waiting if another thread is already holding the lock. The class java.util.concurrent.locks.ReentrantReadWriteLock
can be used when a thread requires a lock to write information while other threads require the lock to simultaneously read the information.
Noncompliant Code Example (addition)
In this noncompliant code example, the two fields a
and b
may be set by multiple threads, using the setValues()
method. While getSum()
is always guaranteed to return a sum, that sum might be erroneous.
...
For instance, if a
and b
currently have the value 0, and one thread calls getSum()
while another calls setValues(1, 1)
, then getSum()
might return 0, 1, or 2. Of these, the value 1 is unacceptable; it is returned when the first thread reads a
and b
after the second thread has set the value of a
but before it has set the value of b
.
Compliant Solution (addition)
This compliant solution synchronizes the setValues()
method so that the entire operation is atomic.
Code Block | ||
---|---|---|
| ||
private volatile int a; private volatile int b; public synchronized int getSum() { return a + b; } public synchronized int setValues(int a, int b) { this.a = a; this.b = b; } |
...