2

I understand what synchronize and volatile does and where they are used. I just learned volatile and I was confused about when could we use synchronize without volatile. if I synchronize an object I need to block other threads from using the same object , but in most cases I would do that to edit the object, if so I need to have volatile on that attributes I'm editing .

The following code is about race condition and I wonder why I've never seen someone using volatile on count variable :

  public synchronized void add(int value){
      this.count += value;
  }

shouldn't be count volatile here ?

I'm just trying to figure a case where synchronize can be used without volatile , a piece of code will help.

Mohammad Karmi
  • 1,403
  • 3
  • 26
  • 42

1 Answers1

1

It is evident that volatile is not strong enough to implement a counter because it does not guarantee atomicity. However, if reads greatly outnumber modifications, you can combine intrinsic locking and volatile variables to reduce the cost on the common code path. Check this out,

public class Counter {
    @GuardedBy("this") private volatile int value;

    public int getValue() { return value; }

    public synchronized int increment() {
        return value++;
    }
}

The code uses synchronized to ensure that the increment operation is atomic and uses volatile to guarantee the visibility of the current result. If updates are infrequent, this approach may perform better as the overhead on the read path is only a volatile read, which is generally cheaper than a lock acquisition.

Ravindra Ranwala
  • 20,744
  • 6
  • 45
  • 63
  • 1
    synchronize shouldn't be enough right ? I was wondering why no one using it in their examples. can I have example for synchronize alone without volatile ? I can't seem to find one because every edit should be visible. – Mohammad Karmi Oct 13 '18 at 07:52
  • Here you have both `synchronized` and `volatile`. You can `synchronize` the `getValue()` method too instead of marking it as `volatile` but that would be costly as the answer explains. – Ravindra Ranwala Oct 13 '18 at 07:55
  • if I synchronize getValue I still need the volatile , how could other threads have the changes visible ? – Mohammad Karmi Oct 13 '18 at 07:56
  • 1
    If you `synchronize` it then the `volatile` is no longer needed. But that will be slow since it involes a heavy lock acquisition. – Ravindra Ranwala Oct 13 '18 at 08:14
  • @ Ravindra Ranwala why it is not needed ? does synchronize forces read from memory ? – Mohammad Karmi Oct 13 '18 at 08:15
  • 2
    `synchronized` provide you visibility same as `volatile`. So it is not needed. – Ravindra Ranwala Oct 13 '18 at 08:21
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/181800/discussion-between-mohammad-karmi-and-ravindra-ranwala). – Mohammad Karmi Oct 13 '18 at 08:21
  • Don't do discussions in chat, coz others will miss that. This site is mainly for learning purpose. So the chatting primarily violates it's main intention. – Ravindra Ranwala Oct 13 '18 at 08:22
  • @Ravidra no discussion I didnt want to post many messages , it is just add this to the answer "synchronized provide you visibility same as volatile. So it is not needed" which was my question on do we need both together or not – Mohammad Karmi Oct 13 '18 at 08:24
  • @ Ravindra Ranwala if you have any doucment about synchronized provide you visibility same as volatile. it will be great – Mohammad Karmi Oct 13 '18 at 08:28
  • 1
    @MohammadKarmi https://stackoverflow.com/questions/18485791/what-are-read-barriers-and-write-barriers-in-synchronized-block https://riptutorial.com/java/example/10870/visualizing-read-write-barriers-while-using-synchronized---volatile https://dzone.com/articles/memory-barriersfences https://www.infoq.com/articles/memory_barriers_jvm_concurrency – Peter Lawrey Oct 13 '18 at 09:23
  • 2
    @PeterLawrey Thanks for the documents but I have one doubt, does synchronize always ensure to read consistent data even if that data was manipulated by non-synchronized block ? synchronized method A(){ this.count // will it always read latest changes if another thread modifies it in B() method ? } method B(){ this.conunt++; ....} – Mohammad Karmi Oct 13 '18 at 10:13
  • Read this book https://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601 – Ravindra Ranwala Oct 13 '18 at 10:38
  • 1
    @RavindraRanwala thanks , but can you please provide me an answer for the question I tagged Peter on ? – Mohammad Karmi Oct 13 '18 at 10:50
  • @MohammadKarmi No, synchornized only guarantees visibility of changes that were made within synchronized blocks of the same lock. However that was a good question. – Ravindra Ranwala Oct 13 '18 at 13:04
  • @MohammadKarmi The writer needs a write barrier and the reader needs a read barrier. Otherwise, the value write might not get propagated. – Peter Lawrey Oct 13 '18 at 13:22
  • @PeterLawrey is this sentence true "The thread memory flushes all its variables, i.e. it has all of its variables effectively read from "main" memory ." I read it from here http://javaexp.blogspot.com/2007/12/difference-between-volatile-and.html. if the sentence above is true then visibility will be guaranteed on changes from different locks . – Mohammad Karmi Oct 13 '18 at 14:46
  • @PeterLawrey this is my question https://stackoverflow.com/questions/52794312/synchronize-on-different-object-visbility – Mohammad Karmi Oct 13 '18 at 15:07