Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: can we agree on this noncompliant code example?

...

Pre- and post-increment and pre- and post-decrement operations in Java are non-atomic in that the value written depends upon the value initially read from the operand. For example, x++ is non-atomic because it is a composite operation consisting of three discrete operations: reading the current value of x, adding one to it, and writing the new, incremented value back to x.

This noncompliant code example contains a data race that may result in the itemsInInventory field being incorrectly decrementedmissing the fact that callers returned or removed items.

Code Block
bgColor#FFcccc

public class InventoryManagement {

  private static final int MIN_INVENTORY = 10;
  private static final int MAX_INVENTORY = 500;

  private int itemsInInventory = 100;

  public final intvoid removeItem() {
    if (itemsInInventory > 0<= MIN_INVENTORY()) {
    return itemsInInventory--; throw // Returns new count of items in inventory
  IllegalStateException("under stocked");
    }
  return  itemsInInventory--1; //
 Error code
}

  public final intvoid returnItem() {
    if (itemsInInventory == Integer.MAX_VALUEINVENTORY) {
  // Check for integer overflow
throw new   return -1; // Error Code
  }
  returnIllegalStateException("over stocked");
    }
    itemsInInventory++;
  }

} 

For example, if the removeItem() method is concurrently invoked by two threads, t1 and t2, the execution of these threads may be interleaved so that:

...

Time

itemsInInventory=

Thread

Action

1

100

t1

reads the current value of itemsInInventory

...

, 100, into a temporary variable

2

100

t2

reads the current value of itemsInInventory, (still) 100, into a temporary variable

3

100

t1

decrements the temporary variable to 99

4

100

t2

decrements the temporary variable to 99

5

99

t1

writes the temporary variable value to itemsInInventory

6

99

t2

writes the temporary variable value to itemsInInventory

As a result, the effect of the call by t1 is not reflected in itemsInInventory. It is as if the call was never made. This "lost call" phenomenon can occur with concurrent calls to returnItem() or concurrent calls to removeItem() and returnItem()

As a result, a decrement operation is "lost" and the itemsInInventory value is now incorrect.

Similarly, the returnItem() method that increments itemsInInventory is also non-atomic.

Noncompliant Code Example (volatile)

...