Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: reviewed and updated to first compliant solution

...

For atomicity of a grouping of calls to independently atomic methods belonging to the thread-safe classes, see CON07-J. Do not assume that a grouping of calls to independently atomic methods is atomic.

The Java Language Specification also permits reads and writes of 64-bit values to be non-atomic though this is not an issue with most modern JVMs (see CON25-J. Ensure atomicity when reading and writing 64-bit values).

...

Code Block
bgColor#FFcccc
final class Flag {
  private boolean flag = true;
 
  public void toggle() {  // Unsafe
     flag = !flag; 
  }

  public boolean getFlag() { // Unsafe 
    return flag;
  }
}

It is prone to Execution of this code may result in a data race because the value of flag is read, negated, and written back.

AlternativelySimilarly, the toggle() method can use the compound assignment operator ^= to negate the current value of flag.

Code Block
bgColor#FFcccc
final class Flag {
  private boolean flag = true;
 
  public void toggle() {  // Unsafe
    flag ^= true;  // Same as flag = !flag; 
  }

  public boolean getFlag() { // Unsafe 
    return flag;
  }
}

This attempt code is also not thread-safe. A data race exists because ^= is a non-atomic compound operation.

Consider, for example, two threads that call toggle(). The effect of toggling flag twice is expected to restore it to its original value. However, the following scenario leaves flag in the wrong incorrect state:

Time

flag=

Thread

Action

1

true

t1

reads the current value of flag, true, into a temporary variable

2

true

t2

reads the current value of flag, (still) true, into a temporary variable

3

true

t1

toggles the temporary variable to false

4

true

t2

toggles the temporary variable to false

5

false

t1

writes the temporary variable's value to flag

6

false

t2

writes the temporary variable's value to flag

As a result, the effect of the call by t2 is not reflected in flag; the program behaves as if the call was never made.

Noncompliant Code Example (volatile variable)

This noncompliant code example derives from the preceding one but declares Declaring flag as volatile . also does not help:

Code Block
bgColor#FFcccc
final class Flag {
  private volatile boolean flag = true;
 
  public void toggle() {  // Unsafe
    flag ^= true; 
  }

  public boolean getFlag() { // Safe
    return flag;
  }
}

It is still insecure This code remains unsuitable for multithreaded use because declaring a variable as volatile does not guarantee the visibility of updates to the shared variable flag when a compound operation is performed. In other words, the value of the write depends on the current value of the variablethat compound operations on that variable are performed atomically.

Compliant Solution (synchronization)

...