Can we achieve visibility and atomicity using Volatile and Synchronized together?

60 views Asked by At

I am just trying to understand... Will I achieve the same result using the below two approaches? I mostly see the first approach only. Is there anything wrong with the second approach? We can use AtomicInteger to achieve the same but just wanted to know. Can someone please clarify?

Approach#1

public class Counter {
   private int counter = 0;
   
   public int getCount() {
      synchronized(this) {
         return counter;
      }
   }

   public void increment() {
      synchronized(this) {
         counter++;
      }
   }
}

Approach#2

public class Counter {
   private volatile int counter = 0;
   
   public int getCount() {
      return counter;
   }

   public synchronized void increment() {
      counter++;
   }
}
2

There are 2 answers

0
ciamej On

Michael's comment is correct. Both approaches are fine.

In terms of performance, it is difficult to say which one is better. It might even depend on the architecture (x86 vs ARM).

The second one might be better for gets, but worse for increments (because both the lock is taken, and a write memory barrier is issued, unless JIT can optimize that away...)

0
Solomon Slow On

You never need volatile if you're using synchronized. Both keywords establish a "happens before" relationship between events in different threads.

  • Whatever some thread A does before it writes a value to some volatile variable, v, is guaranteed to be visible to some other thread B after B subsequently reads the same variable, v.

  • Whatever some thread A does before it exits from a synchronized(o) block is guaranteed to be visible to thread B after B subsequently enters a block that is synchronized on the same object, o.