Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: tweaks

...

The Java Language Specification also permits reads and writes of 64-bit values to be non-atomic (see CON25-J. Ensure atomicity when reading and writing 64-bit values).

Noncompliant Code Example (

...

logical negation)

This noncompliant code example declares a shared boolean variable flag and provides a toggle() method that negates the current value of flag.

...

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

Similarly, 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 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 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

...

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 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 (bitwise negation)

Similarly, 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 code is also not thread-safe. A data race exists because ^= is a non-atomic compound operation.

Noncompliant Code Example (volatile)

Declaring flag as volatile also does not help:

...

The second execution order involves the same operations, just that t2 starts and finishes before t1.

Compliance with the guideline CON04-J. Synchronize using an internal private final lock object can reduce the likelihood of misuse by ensuring that untrusted callers cannot access the lock object.

Compliant Solution (volatile-read, synchronized-write)

...

Note that declaring the variables as volatile does not resolve the issue because these compound operations involve reads and writes of multiple variables. Also, this code does not

This code also fails to prevent integer overflow. See INT00-J. Perform explicit range checking to ensure integer operations do not overflow for more information.

...