1
public class Volatile {

    volatile int x = 0;

    public static void main(String a[]) {
        Volatile y = new Volatile();
        test t1 = new test(y);
        test t2 = new test(y);
        t1.setName("A");
        t2.setName("B");
        t1.start();
        t2.start();
    }
}

class test extends Thread {

    Volatile v;

    test(Volatile v) {
        this.v = v;
    }

    @Override
    public void run() {
        for (int i = 0; i < 4; i++) {
            System.out.println(Thread.currentThread().getName() + "Says Before " + v.x);
            v.x++;
            System.out.println(Thread.currentThread().getName() + "Says After " + v.x);
        }
    }
}

Output

ASays Before 0
BSays Before 0
BSays After 2
BSays Before 2
BSays After 3
ASays After 1   <--- Is it a cache value ?
BSays Before 3
ASays Before 3
BSays After 4
BSays Before 5
BSays After 6
ASays After 5    <--- Is it a cache value ?
ASays Before 6
ASays After 7
ASays Before 7
ASays After 8

Everywhere, I found common point about volatile

guaranteeing that it will not be cached and that different threads will see the updated value

But, from my above example, threads have different values (old/cache values) or is it because of improper implementation ?

Ravi
  • 30,829
  • 42
  • 119
  • 173
  • Have you looked at [Atomic Access](https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html)? – MadProgrammer Jul 28 '15 at 04:05
  • @MadProgrammer It says *changes to a volatile variable are **always** visible to other threads* – Ravi Jul 28 '15 at 04:13
  • Yes, that is true, but the question remains of WHEN those changes are actually committed... – MadProgrammer Jul 28 '15 at 04:19
  • @MadProgrammer you mean, we will never be sure, whether incremental was completed or not. Am I right ? If it, then we can never predict the volatile variable value in multi threading env. right ? – Ravi Jul 28 '15 at 04:23
  • Pretty much, the linked answer has some interesting points about this, so you could use `synchronized` and `volatile` together or make use of the `Atomic` API which gives you some other options – MadProgrammer Jul 28 '15 at 04:26

1 Answers1

2

Marking a variable volatile will prevent the JVM from caching the value but it will not take care of synchronisation issues for you (such as the thread being swapped out between modifying the variable and printing it).

For example, thread A outputs before 0 then is swapped out so that thread B runs. The value is still zero because A hasn't yet updated it. B then updates it and then A comes back in and updates it as well, then prints it. That means you could end up with something like:

ASays Before 0
BSays Before 0
ASays After 2

which is less than ideal.

In addition, the println itself is not atomic so it can be interrupted mid-stream, causing the thread to be holding an outdated value for printing (i.e., one that shows up later in the output stream thatn it would ideally).

To properly update and print, you should use synchronized around blocks that require the variable to be used atomically, something like:

synchronized (this) {
    System.out.println(Thread.currentThread().getName() + " before " + v.x);
    v.x++;
    System.out.println(Thread.currentThread().getName() + " after " + v.x);
}

In your particular case however, you cannot use this since it's the thread object, meaning that there's two of them, hence they won't block each other as you need.

You can get around that with a bit of a kludge, introducing a static object into the thread class:

static Object o = new Object();

and using that for synchronisation:

synchronized (o) {
    System.out.println(Thread.currentThread().getName() + " before " + v.x);
    v.x++;
    System.out.println(Thread.currentThread().getName() + " after " + v.x);
}
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 1
    Please correct me, then why should I use volatile ? If I will synchronized, then I can use simple non-volatile variable. That will result same. Am I right ? – Ravi Jul 28 '15 at 04:15
  • Also, I made changes as you said, I still see same pattern of values. – Ravi Jul 28 '15 at 04:18
  • @jWeaver `synchronised` will protect from modifications been made, but not if the data is cached, where as volatile should prevent the values from been cached and giving you real time access, it's a balancing act. Recently, I've used the `Atomc` classes over volatile – MadProgrammer Jul 28 '15 at 04:18
  • I tend to prefer sync operations since there's a whole raft of cases where volatile doesn't help. As one example, it's no good when you want a consistent value for print-modify-print such as you have. In fact, I seem to recall that it's unsuitable for modifying variables based on their old valued because Java doesn't guarantee the `x++` is always atomic. – paxdiablo Jul 28 '15 at 04:24
  • @jWeaver, apologies for that, turns out `this` in your case was one of the two distinct thread objects so they won't sync. Modified answer to work around that. – paxdiablo Jul 28 '15 at 04:35
  • @paxdiablo I have a question. I was trying to differentiate between non-volatile variable, volatile variable and static variable. I see all three variable showing same output. Is it obvious ? Since, I was expecting different output in case of non-volatile variable. :S – Ravi Jul 28 '15 at 04:41
  • @jWeaver, you may get the same output, it depends entirely on how threads are scheduled. That's a non-deterministic thing. – paxdiablo Jul 28 '15 at 05:20