29

We often use volatile to ensure that a condition variable can be visible to every Thread.

I see the volatile fields are all primitive type in code so far.

Does object field has this problem? For example:

class a {

   public String str;

   public List list;

}

If there are some threads which will access str and list, must I add 'volatile'?

I guess each access to Object will get directly from Heap, and the Object will not be cached like primitive type.

Is that right?

Paŭlo Ebermann
  • 73,284
  • 20
  • 146
  • 210
Hesey
  • 4,957
  • 6
  • 31
  • 31

2 Answers2

34

You have to distinguish between the object reference and the actual object.

  • For the reference your field modifier is relevant. When you change the reference to a different object (i.e. reference a different String) the change might not be noticed by a different Thread. If you want to enforce visibility you have to use final or volatile.

  • The actual object on the heap is not affected by the field modifier. Instead how you see each field of this object is determined by its own field modifier according to the same rules (is it volatile or final? If not, visibility for concurrent Threads is not enforced)

So the answer is: Yes, you have to add volatile or final. Stylistically it would be much better to make the field final, though. It has the same effect Thread-wise but is a stronger statement, too: This field cannot be changed - which is the reason why it can be cached heedlessly by the JVM. And for the same reason it comes with a little performance benefit compared to volatile, Java needs not care whether the field is changes again and does not need to add overhead.

Stefan Schubert-Peters
  • 5,419
  • 2
  • 20
  • 21
1

You add volatile keyword to tell the compiler that its bound to change. so that all threads re-confirm that their local cached copy is same as that of original one, if there are changes it updates it. and you find it usually with Primitives because usually primitive values are incremented or decremented etc by different threads. but Object, especially List will never change since its just a reference to the Object. if you are assigning different objects to the same variable, at run-time then you may do..

Suma
  • 33,181
  • 16
  • 123
  • 191
ngesh
  • 13,398
  • 4
  • 44
  • 60
  • You mean the reference may be cached like primitive? – Hesey Aug 16 '11 at 09:17
  • 1
    What i I have a field (Object o = null;) but it cannot be set final because it is initialized outside of the constructor, however - it is never changed to any other value after initialization - and it is not read while it is null (not even to check for null)... it is only read after it has been initialized. In this case, nothing special needs to be done - right? (multiple threads can access the object) – ycomp Oct 19 '15 at 15:08
  • if references are cached , how come updates done by thread1 is visible to thread2 ? does final guarantee that ? how its thread safe – amarnath harish May 26 '18 at 06:06
  • @ycomp yes as long as no updates were made to that object its perfectly fine to read them. – amarnath harish May 26 '18 at 06:08