2

While reading "Java Concurrency in Practice", I came across the following -

To publish an object safely, both the reference to the object and the object's state must be made visible to other threads at the same time. A properly constructed object can be safely published by:

  • Initializing an object reference from a static initializer;
  • Storing a reference to it into a volatile field or AtomicReference;
  • Storing a reference to it into a final field of a properly constructed object; or
  • Storing a reference to it into a field that is properly guarded by a lock.

My question is - is the second point true? I.e. Can I make an Object's state visible to other threads just by storing a reference to it in a volatile reference? If not, am I reading the above points incorrectly?

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
Ashutosh A
  • 975
  • 7
  • 10
  • Do you understand what "safely published" means in this context? – Matt Ball Mar 24 '16 at 13:07
  • 1
    http://stackoverflow.com/q/801993/139010 – Matt Ball Mar 24 '16 at 13:08
  • 1
    In my opinion (happy to be corrected) it means that the reading thread should be able to see the correct values of the members of that object (correct values - values that were assigned to the members in the constructor of that object) – Ashutosh A Mar 24 '16 at 13:09
  • 3
    Yes, it is true. A volatile write creates a happens-before relationship with any subsequent volatile reads (of the same variable). There is also a happens-before relationship within a single thread. Add to that the fact that h-b is transitive, and it means that anything the writing thread had done before storing a volatile reference will be visible to any other thread that has read the volatile reference. This is true to any fields of any object, by the way, so you could have five non-volatile writes anywhere, followed by a volatile "guard" write. – biziclop Mar 24 '16 at 13:10
  • @MattBall - thanks for the formatting and the link! Really appreciated :) I read that link prior to posting however it did not provide a precise/clear-cut answer to my question ... maybe I didn't read carefully enough... – Ashutosh A Mar 24 '16 at 13:14
  • @biziclop - Thanks! However, any code written in the first thread prior to writing that volatile field could have been reordered by the compiler to execute AFTER the volatile write right? – Ashutosh A Mar 24 '16 at 13:20
  • 3
    @AshutoshAgrawal No. The reading thread, after reading the volatile reference, cannot see a state when a write that came before the volatile write hasn't happened. This is why it's important that happens-before is transitive. – biziclop Mar 24 '16 at 13:26
  • @biziclop, thanks so much for replying! Just one last thing - any writes that happen before the volatile write don't have a h-b relation with the volatile write, correct? (in a scenario where the volatile write doesn't "depend" on the results of the previous write's, which is when the compiler can reorder those). Sincere apologies if I am just not getting the points you made ... – Ashutosh A Mar 24 '16 at 13:38
  • 1
    Program order [always creates a happens-before relationship](https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4.5). The other important caveat is this: `It should be noted that the presence of a happens-before relationship between two actions does not necessarily imply that they have to take place in that order in an implementation. If the reordering produces results consistent with a legal execution, it is not illegal. ` This means that so long as your code is correctly synchronized, it is guaranteed you won't see the effect of any reordering. – biziclop Mar 24 '16 at 13:46
  • @biziclop Thanks!!! That does clarify it. – Ashutosh A Mar 26 '16 at 02:51
  • Found a good article - http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html – Ashutosh A Mar 29 '16 at 10:11

1 Answers1

2

Making object volatile doesn't make his state published to all the Threads, ie

volatile A a = new A();
private static class A {
    int i = 0;
    int j = 0;
    int k = 0;
}

is not the same as

A a = new A();
private static class A {
    volatile int i = 0;
    volatile int j = 0;
    volatile int k = 0;
}

(1) rather makes your reference volatile, ie if one Thread reassigns the reference, this reassignment will be "published" to other Threads immediately

Anton Dovzhenko
  • 2,399
  • 11
  • 16
  • Thanks for the answer! Apparently, even if just the reference is volatile, it is enough. Any thread that reads the reference will also see any writes that were done BEFORE the volatile reference itself was set (assuming the the other writes were done by the same thread which had set the volatile reference) – Ashutosh A Mar 30 '16 at 07:09