3

Consider the snippet:

class Mutable {
    private volatile int value;
    public int get()
    {
        return value;
    }
    public int set(int value)
    {
        this.value = value;
    }
}

class Test {
    public volatile Mutable m;
}

So using the following sequence:

Thread-1: get()     // returns 2
Thread-2: set(3)
Thread-1: get()     // guaranteed to return 3 due to volatile with property value

But I am unable to understand the following note by the author-

one note however, when m is assigned, the internal value will be correctly visible. it is only after subsequent calls to set() which do not write m that you have problems.

Please exemplify. Which problem is he talking about?

Farhan stands with Palestine
  • 13,890
  • 13
  • 58
  • 105

2 Answers2

3

So the reason that last comment is confusing, is because it got taken out of context. The example code you provided is different from the original code to which that comment was directed. in the original code, value was not volatile. When value is not volatile, then you have the following situation.

Thread1:

Mutable tmp = new Mutable();
tmp.set(3);
Test.m = tmp;

Thread2:

Test.m.get();  // *** this is guaranteed to return 3 due to the happens before rules.

Thread1:

Test.m.set(5);

Thread2:

Test.m.get();  // no guaranatees here, could be 3, could be 5

My comment was referring to the "***" part, where the volatile assignment of m provides the happens before relationship which makes "3" visible to to Thread2 (due to the volatile read of m). (to re-iterate, value is not volatile in this example).

Community
  • 1
  • 1
jtahlborn
  • 52,909
  • 5
  • 76
  • 118
  • Don't you think when value is not volatile, then the statements `1 - tmp.set(3);` & `2 - Test.m = tmp;` executed by the thread 1 could be re-ordered and at the same time if Thread 2 were to execute Test.m.get();, it might get the default value of instance variable value i.e 0. Or are you assuming that Thread 2 will be executing the code snippet much later after Thread 1 has executed. – Farhan stands with Palestine Aug 22 '16 at 14:23
  • @ShirgillFarhanAnsari - no. that is one of the guarantees of volatile in the jdk 5+ memory model. the memory model changes included non-volatile changes as part of the happens before relationship created by volatile. that is why volatile has the same memory effects as synchronized in a jdk 5+ world. in other words, the first non-volatile assignment (in `set(3)`) _cannot_ be re-ordered past the volatile assignment of `m`. – jtahlborn Aug 22 '16 at 15:46
  • Impressive, I surmise you mean - When thread A writes to a volatile variable and subsequently thread B reads that same variable, the values of all variables that were visible to A prior to writing to the volatile variable become visible to B after reading the volatile variable. So from a memory visibility perspective, writing a volatile variable is like exiting a synchronized block and reading a volatile variable is like entering a synchronized block. – Farhan stands with Palestine Aug 22 '16 at 15:48
  • @ShirgillFarhanAnsari - that is pretty much exactly correct. – jtahlborn Aug 22 '16 at 15:49
1

I believe, the problematic part is that the volatile guarantees a happens-before relationship between read and write accesses. We just don't know what will happen with quick write operators:

Thread-1: get()     // returns 2

// no real happens-before on the 3 lines below:
Thread-2: set(3)
Thread-3: set(4)
Thread-4: set(5)

// now what?
Thread-1: get()     // guaranteed to return 3 or 4 or 5 due to volatile with property value

A more tricky case is the incrementing a counter:

Thread-1: get()     // returns 2

// no real happens-before on the 3 lines below. They all might increment the 2:
Thread-2: set(get()+1)
Thread-3: set(get()+1)
Thread-4: set(get()+1)

// now what?
Thread-1: get()     // guaranteed to return 3 or 4 or 5 due to volatile with property value
Tamas Rev
  • 7,008
  • 5
  • 32
  • 49
  • I would say that due to presence of `volatile` keyword on `value`, the first code snippet of your would definitely return `5` as volatile guarantees that. Second one I am unsure. – Farhan stands with Palestine Aug 22 '16 at 09:00
  • The point with the first snippet is that I had to write the threads in some order. The `jvm` doesn't have to do that. Those sets can occur parallelly. – Tamas Rev Aug 22 '16 at 09:16
  • Thanks. +1 for statements re-ordering. – Farhan stands with Palestine Aug 22 '16 at 11:08
  • This answer doesn't say much about the happens before relationship, it just points out the nondeterminate nature of parallelism and the fact that volatile members are not atomic. – jtahlborn Aug 22 '16 at 14:09
  • @jtahlborn indeed. This answer provides some examples when there's no happens-before relationship. As far as I understood, this is what the OP asked. Also, this answer doesn't pretend to explain the happens-before relationship. – Tamas Rev Aug 22 '16 at 14:35