Search code examples
javasynchronizationsynchronizedthread-synchronization

Atomic variables in synchronized blocks


I'm referring to the Java language but I think it can concern other languages as well.

The question is: does it make sense to put an atomic variable in a synchronized block? Or the fact that the synchronized block will not be executed by two threads at the same time is enough to guarantee that the operations performed in the synchronized block are atomic? (Example 1 vs. Example 2)

Example 1:

public class SharedVariables {
  public static AtomicInteger i;
}

public class MyThread extends Thread {
  public void run() {
    synchronized(SharedVariables.i) {
      i.getAndIncrement();
    }
  }
}

Example 2:

public class MyIntegerWrapper {
  public int i;
  public void increment() {
    this.i++;
  }
}

public class SharedVariables {
  public static MyIntegerWrapper i;
}

public class MyThread extends Thread {
  public void run() {
    synchronized(SharedVariables.i) {
      i.increment();
    }
  }
}

Solution

  • Not by itself no. But if you're doing an operation that involves a thread-safe class like AtomicInteger and other variables (even if they're other AtomicIntegers), you might need to.

    AtomicInteger guarantees that operations on it are thread-safe and atomic without you needing to do anything. But let's say that you increment one and decrement another, and their sum always needs to be the same. You have 2 atomic operations, but to combine them into a single atomic operation you'll need additional synchronization. Only then can you be sure that other threads will read a constant sum of those variables.

    I'd still be careful when combining manual synchronization with java.util.concurrent classes, as there's most likely a far cleaner solution provided by the concurrent classes.