Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Added ThreadSafe detection

...

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

Code Block
bgColor#FFcccc

final class Flag {
  private boolean flag = true;

  public void toggle() {  // Unsafe
    flag = !flag;
  }

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

...

The toggle() method may also 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;
  }
}

...

Declaring flag volatile also fails to solve the problem:

Code Block
bgColor#FFcccc

final class Flag {
  private volatile boolean flag = true;

  public void toggle() {  // Unsafe
    flag ^= true;
  }

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

...

This compliant solution declares both the toggle() and getFlag() methods as synchronized.

Code Block
bgColor#ccccff

final class Flag {
  private boolean flag = true;

  public synchronized void toggle() {
    flag ^= true; // Same as flag = !flag;
  }

  public synchronized boolean getFlag() {
    return flag;
  }
}

...

In this compliant solution, the getFlag() method is not synchronized, and flag is declared as volatile. This solution is compliant because the read of flag in the getFlag() method is an atomic operation and the volatile qualification assures visibility. The toggle() method still requires synchronization because it performs a nonatomic operation.

Code Block
bgColor#ccccff

final class Flag {
  private volatile boolean flag = true;

  public synchronized void toggle() {
    flag ^= true; // Same as flag = !flag;
  }

  public boolean getFlag() {
    return flag;
  }
}

...

This compliant solution uses a read-write lock to ensure atomicity and visibility.

Code Block
bgColor#ccccff

final class Flag {
  private boolean flag = true;
  private final ReadWriteLock lock = new ReentrantReadWriteLock();
  private final Lock readLock = lock.readLock();
  private final Lock writeLock = lock.writeLock();

  public void toggle() {
    writeLock.lock();
    try {
      flag ^= true; // Same as flag = !flag;
    } finally {
      writeLock.unlock();
    }
  }

  public boolean getFlag() {
    readLock.lock();
    try {
      return flag;
    } finally {
      readLock.unlock();
    }
  }
}

...

This compliant solution declares flag to be of type AtomicBoolean.

Code Block
bgColor#ccccff

import java.util.concurrent.atomic.AtomicBoolean;

final class Flag {
  private AtomicBoolean flag = new AtomicBoolean(true);

  public void toggle() {
    boolean temp;
    do {
      temp = flag.get();
    } while (!flag.compareAndSet(temp, !temp));
  }

  public AtomicBoolean getFlag() {
    return flag;
  }
}

...

In this noncompliant code example, multiple threads can invoke the setValues() method to set the a and b fields. Because this class fails to test for integer overflow, users of the Adder class must ensure that the arguments to the setValues() method can be added without overflow. (See rule NUM00-J. Detect or prevent integer overflow for more information.)

Code Block
bgColor#FFcccc

final class Adder {
  private int a;
  private int b;

  public int getSum() {
    return a + b;
  }

  public void setValues(int a, int b) {
    this.a = a;
    this.b = b;
  }
}

...

In this noncompliant code example, a and b are replaced with atomic integers.

Code Block
bgColor#FFcccc

final class Adder {
  private final AtomicInteger a = new AtomicInteger();
  private final AtomicInteger b = new AtomicInteger();

  public int getSum() {
    return a.get() + b.get();
  }

  public void setValues(int a, int b) {
    this.a.set(a);
    this.b.set(b);
  }
}

...

This compliant solution synchronizes the setValues() and getSum() methods to ensure atomicity.

Code Block
bgColor#ccccff

final class Adder {
  private int a;
  private int b;

  public synchronized int getSum() {
    // Check for overflow 
    return a + b;
  }

  public synchronized void setValues(int a, int b) {
    this.a = a;
    this.b = b;
  }
}

...

Some available static analysis tools can detect the instances of nonatomic update of a concurrently shared value. The result of the update is determined by the interleaving of thread execution. These tools can detect the instances where thread-shared data is accessed without holding an appropriate lock, possibly causing a race condition.

 ToolVersion Description 
ThreadSafe
Include Page
ThreadSafe_V
ThreadSafe_V
Implemented

Related Guidelines

MITRE CWE

CWE-667. Improper locking

 

CWE-413. Improper resource locking

 

CWE-366. Race condition within a thread

 

CWE-567. Unsynchronized access to shared data in a multithreaded context

...

[API 2006]

Class AtomicInteger

[Bloch 2008]

Item 66. Synchronize access to shared mutable data

[Goetz 2006]

2.3, Locking

[JLS 2005]

Chapter 17, Threads and Locks

 

§17.4.5, Happens-Before Order

 

§17.4.3, Programs and Program Order

 

§17.4.8, Executions and Causality Requirements

[Lea 2000]

Section 2.2.7, The Java Memory Model

 

Section 2.1.1.1, Objects and Locks

[Tutorials 2008]

Java Concurrency Tutorial

 

      07. Visibility and Atomicity (VNA)