Will mutations of a volatile variable be visible to all threads?

148 views Asked by At

Let's say I have a volatile reference c to MyClass, and MyClass has an integer field x. If one thread changes the value of x, will the new value be guaranteed visible to all other threads, or does x have to be volatile too?

In other words, is the example below guaranteed to print 2?

public class MyClass {

private static volatile MyClass c;

private int x = 1;

public static void main(String[] args) {
    c = new MyClass();
    Thread thread = new Thread(new Runnable() {

        @Override
        public void run() {
            c.x = 2;

        }
    });
    thread.start();
    try {
        thread.join();
        System.out.println(c.x);
    } catch (InterruptedException ex) {
        //
    }


}

If not, what if I want to manipulate an object whose source code I don't control, such as a Collection? How can I ensure that changes to the Collection object are visible to all threads?

2

There are 2 answers

0
Kayaman On

For your first question, yes. Volatile makes sure that writes to the volatile field are seen by other threads' read operations. It doesn't cascade however, so volatile doesn't fit into all use cases (i.e. just because a reference is volatile doesn't mean all the fields of the referred object would magically become volatile).

In most cases you need to synchronize the access to make sure that all writes are seen by subsequent reads.

2
AdamSkywalker On

Varialbe x must be volatile too for your example.

If so, what if I want to manipulate an object whose source code I don't control, such as a Collection? How can I ensure that changes to the collection object are visible to all threads?

To see the changes in a collection (assuming it is not a concurrent collection, let's say it is a plain ArrayList), you should provide a monitor by yourself.

Object monitor = new Object();

synchronized(monitor) {
   // change collection
}

synchronized(monitor) {
   // read collection
}

If read and write operations will be synchronized on monitor, they will work correct. However, if you have code you don't control, and this code modifies collection without synchronization, you can do nothing.

Issue number 2: even with read/write synchronization on monitor, you still can get some ConcurrentModificationExceptions, if you iterate on collection in one thread and modify it in another thread. So read in my example is not a reference read, but a value read.