Question

Does volatile write assure that whatever writes (non-volatile / volatile writes) happens before it in one thread will be visible to other thread?

Will the following given code always produce 90,80 as output?

public class MyClass
{
    private boolean flag = false;
    private volatile int volatileInt = 0;
    private int nonVolatileInt = 0;
    public void initVariables()
    {
        nonVolatileInt = 90; // non-volatile write
        volatileInt = 80; // volatile write
        flag = true; // non-volatile write
    }
    public void readVariables()
    {
        while (flag == false)
        {}
        System.out.println(nonVolatileInt + ","+ volatileInt);
    }
    public static void main(String st[])
    {
        final MyClass myClass = new MyClass();
        Thread writer = new Thread( new Runnable()
        {
            public void run()
            {
                myClass.initVariables();
            }
        });
        Thread reader = new Thread ( new Runnable()
        {
            public void run()
            {
                myClass.readVariables();
            }
        });
        reader.start();writer.start();
    }
}

My concern is the method initVariables(). Isn't JVM has a freedom to reorder the code blocks in following way?:

flag = true;
nonVolatileInt = 90 ; 
volatileInt = 80;

And consequently, we get the output by the reader thread as : 0,0
Or, they can be reordered in the following way:

nonVolatieInt = 90;
flag = true;
volatileInt = 80;

And consequently, we get the output by the reader thread as : 90,0

Was it helpful?

Solution

A volatile write ensures that writes already performed do not appear after this write. However to ensure you see this you need to perform a volatile read first.

And consequently, we get the output by the reader thread as : 90,0

Correct. However if you perform your reads correctly you cannot get 0, 80

0, 0 - ok
90, 0 - ok
90, 80 - ok
0, 80 - breaks happens before.

However, your reads do not ensure happens before behaviour as it doesn't perform the volatile read first.

System.out.println(nonVolatileInt + ","+ volatileInt);

This reads the non-volatile fields first, so you could see an old version of the non-volatile field and a new version of the volatile field.

Note: in reality, you are highly unlikely to see a problem. This is because caches invalidate a whole cache line at a time and if these fields are in the same 64-byte block, you shouldn't see an inconsistency.

What is more likely to be a problem is this loop.

 while (flag == false)
    {}

The problem is; the JIT can see your thread nevers writes to flag so it can inline the value. i.e. it never needs to read the value. This can result in an infinite loop.

http://vanillajava.blogspot.co.uk/2012/01/demonstrating-when-volatile-is-required.html

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top