itspr
itspr

Reputation: 343

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

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++;
   }
}

Upvotes: 1

Views: 60

Answers (2)

Solomon Slow
Solomon Slow

Reputation: 27115

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.

Upvotes: 1

ciamej
ciamej

Reputation: 7068

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...)

Upvotes: 1

Related Questions