0

Scenario:

class Foo {

    volatile Bar bar;
}

class Bar {

    int baz;
}

for (int i = 0; i < n; i++) {
    Bar bar = new Bar();
    bar.baz = 1;
    foo.bar = bar;
} 

Is is guaranteed that baz variable will be always visible, if Bar isn't immutable (baz isn't final or volatile) but baz never changes after bar assignment?

3zmo
  • 73
  • 9

1 Answers1

1

The volatile is applied only to the variable where you define it.

If you need to be sure that your code works also for nested variables you need to define them volatile too.

As an alternative you can encapsulated the code accessing Bar variable and nested variables in a synchronized block.

The volatile keyword grants that the variable is taken from the main memory instead from the registries of the cpu. This grants that:

… the volatile modifier guarantees that any thread that reads a field will see the most recently written value. - Josh Bloch

This happens to the variable declared volatile, not to the inner fields. You can use the volatile keyword on the baz variable and in this case you are sure that the code works.

Davide Lorenzo MARINO
  • 26,420
  • 4
  • 39
  • 56
  • Thanks, so the answer is NO? Even if I assign bar to volatile foo.bar AFTER bar.baz assignment, is there no guarantee that bar.baz will be visible? – 3zmo Nov 19 '21 at 07:49
  • The problem is not if it is visible or not, but if the value is consistent or not. If two threads works on the value of baz at the same time is possible to have not coherent values. I update the answer to show it – Davide Lorenzo MARINO Nov 19 '21 at 07:52
  • Yes, I can understant that. But let's say I have 1 thread publishing some global configuration (Bar class) and others threads only read that configuration, my only requirement is that after foo.bar assignment bar.baz has the latest value (I don't have race condition). I assume it's still not safe? – 3zmo Nov 19 '21 at 08:05
  • You need to define baz as volatile – Davide Lorenzo MARINO Nov 19 '21 at 08:42
  • Thanks you for the answer. I recently came across this question which is very similar to mine: https://stackoverflow.com/questions/10357823/volatile-hashmap-vs-concurrenthashmap/10358047 but the accepted answer stated something opposite: "If you are populating an entirely new HashMap then assigning it to the existing variable, then you use volatile" Could you please refer to this (HashMap obviously is not thread safe)? – 3zmo Nov 19 '21 at 10:56
  • If I always replace foo.bar with a new Bar instance, there is no way for other threads to read bar.baz from their buffer - meaning the first value read will be the current value (bar.baz is never modified) – 3zmo Nov 19 '21 at 11:31
  • There is another accepted answer that says the opposite: https://stackoverflow.com/questions/23855677/java-volatile-reference-to-mutable-object-will-updates-to-the-objects-field "Assigning newly constructed objects to volatile variables works nicely. Every thread, that reads the volatile variable, will see a fully constructed object. There is no need for further synchronization. This pattern is usually seen in combination with immutable types." – 3zmo Nov 19 '21 at 12:33