...
This noncompliant code example attempts to resolve the problem by declaring itemsInInventory
as volatile.
Code Block | ||
---|---|---|
| ||
private volatile int itemsInInventory = 100; public final int removeItem() { if (itemsInInventory > 0) { return itemsInInventory--; // Returns new count of items in inventory } return -1; // Error code } public final int returnItem() { if (itemsInInventory == Integer.MAX_VALUE) { // Check for integer overflow return -1; // Error Code } else { return itemsInInventory++; } } |
Volatile variables are unsuitable when more than one read/write operation needs to be atomic. The use of a volatile variable in this noncompliant code example guarantees that once itemsInInventory
has been updated, the new value is visible to all threads that read the field. However, because the post decrement operator is nonatomic, even when volatile
is used, the interleaving described in the previous noncompliant code example is still possible.
Similarly, the increment composite operation in the returnItem()
method does not perform the increment operation atomicallyis non-atomic.
Compliant Solution (java.util.concurrent.atomic
classes)
The java.util.concurrent
utilities can be used to atomically manipulate a shared variable. This compliant solution uses a {java.util.concurrent.atomic.AtomicInteger
}} variable which allows certain composite operations to be performed atomically.
...
Wiki Markup |
---|
The {{compareAndSet()}} method takes two arguments, the expected value of a variable when the method is invoked and the updated value. This compliant solution uses this method to atomically set the value of {{itemsInInventory}} to the updated value if and only if the current value equals the expected value. \[[API 06|AA. Java References#API 06]\]. The {{for}} loop guarantees the same behavior of the original function, namely that the function succeeds in decrementing {{itemsInInventory}} or an error is returned. |
The returnItem()
method can be fixed by using the java.util.concurrent.atomic.AtomicInteger.getAndIncrement()
method.
...