Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: promoting to draft

Static shared data should not be protected using instance locks because the instance locks are ineffective when two or more instances of the class are created. Consequently, the shared state is not safe for concurrent access unless a static private final lock object is used.

Noncompliant Code Example (non-static lock object for static data)

This noncompliant code example uses a non-static lock object to guard access to a static field counter. If two Runnable tasks , each consisting of a thread are started, they will create two instances of the lock object and lock on each separately.

Code Block
bgColor#FFcccc
public final class CountBoxes implements Runnable {
  private static volatile int counter;
  // ...

  private final Object lock = new Object();    

  public void run() {
    synchronized(lock) {
      counter++; 
      // ... 
    } 
  }

  public static void main(String[] args) {
    Runnablefor(int r1i = new CountBoxes()0;
 i <  Thread t1 = new Thread(r1);2; i++) {
    Runnable r2 =new Thread(new CountBoxes();
    Thread t2 = new Thread(r2);
    t1.start();
    t2.start();}
  }
}

This does not prevent either thread from observing an inconsistent value of counter because the increment operation on volatile fields is not atomic in the absence of proper synchronization.

...

Code Block
bgColor#FFcccc
public final class CountBoxes implements Runnable {
  private static volatile int counter;
  // ...

  public synchronized void run() {
    counter++; 
    // ... 
  }
  // ...
}

The problem is that this In this case, the intrinsic lock is associated with each instance of the class and not with the class object itself. Consequently, threads constructed using different Runnable instances may observe inconsistent values of the counter.

...

Code Block
bgColor#ccccff
public class CountBoxes implements Runnable {
  private static int counter;
  // ...

  private static final Object lock = new Object();    
  
  public void run() {
    synchronized(lock) {
      counter++; 
      // ...
  }
  // ...
}

There is no requirement of for declaring the counter variable as volatile when synchronization is used.

...

Using an instance lock to protect static shared data provides no does not provide any synchronization properties and can lead to non-deterministic behavior.

...