2

From Javadocs

Using volatile variables reduces the risk of memory consistency errors, because any write to a volatile variable establishes a happens-before relationship with subsequent reads of that same variable. This means that changes to a volatile variable are always visible to other threads.

When changes made to a volatile variable are always visible to any other thread, then why volatile variable cant be used in case of multiple threads writing to that variable. Why is volatile only used for cases when one thread is writing or reading to that while the other thread is only reading the variable?

If changes are always visible to other threads, then suppose if thread B wants to write to that variable, it will see the new value(updated by thread A) and update it. And when the thread A again wants to write, it will again see the updated value by thread B and write to it.Where is the problem in that?

In short, i am not able to understand this.

if two threads are both reading and writing to a shared variable, then using the volatile keyword for that is not enough. You need to use synchronization in that case to guarantee that the reading and writing of the variable is atomic.

Diffy
  • 2,339
  • 3
  • 25
  • 47
  • None of the threads has to be "only" reading or writing. The roles of reader and writer can be "fluent" and many more than two threads can participate in this exchange. – Thilo May 25 '15 at 01:31
  • 1
    If a thread is **writing** a value to a variable, when will it **see** (read) a value? Please clarify your last paragraph. – Sotirios Delimanolis May 25 '15 at 01:31
  • @SotiriosDelimanolis, it will not see, but it will encounter its updated value. So it will make a write to the updated value. – Diffy May 25 '15 at 01:33
  • @Thilo, this SO answer says one should be read. http://stackoverflow.com/a/17748517/3292108 – Diffy May 25 '15 at 01:35
  • And also this article http://tutorials.jenkov.com/java-concurrency/volatile.html – Diffy May 25 '15 at 01:35
  • But what different does that make? I don't think I understand your question. – Sotirios Delimanolis May 25 '15 at 01:37
  • @SotiriosDelimanolis, i am not able to understand this "if two threads are both reading and writing to a shared variable, then using the volatile keyword for that is not enough. You need to use synchronization in that case to guarantee that the reading and writing of the variable is atomic.". – Diffy May 25 '15 at 01:39
  • 1
    Ah, then see the [answer given by ruakh](http://stackoverflow.com/a/30430183/438154). The statement refers to a pattern where both the read and write should be done atomically as a single externally visible operation. – Sotirios Delimanolis May 25 '15 at 01:43

2 Answers2

5

There are plenty of purposes that volatile works fine for — but also plenty of purposes that it doesn't. For example, imagine that you have a field like this:

private volatile int i;

and two threads that both run ++this.i: reading this.i and then writing to it.

The problem is that ++this.i is a volatile read followed by a completely separate volatile write. Any number of things could have happened between the read and the write; in particular, you could get a situation where both threads read i before either thread writes to it. The net effect is that the value of i increases by only 1, even though two separate threads both incremented it.

AtomicInteger (and the other atomics) address this sort of problem by allowing you to simultaneously read and write in a single atomic (≈ volatile) step. (They do this by using a compare-and-swap instruction that performs the write only if the value that was read is still the current value. The increment-and-get method just runs a loop that retries this until the write actually succeeds.)

ruakh
  • 175,680
  • 26
  • 273
  • 307
  • Good example. The problem is not that a thread when it reads the field somehow misses updates from another thread (volatile makes sure that this works). The problem is that the field can be changed by another thread *after* you read it, so you cannot really depend on what you just read and need to take extra synchronization steps (to lock the field down for a while). – Thilo May 25 '15 at 01:45
  • @ruakh, suppose if two threads come simultaneously to write to a variable i. Then in this case, wont the write be always thread safe? Because the other thread will always write to the latest value. – Diffy May 25 '15 at 01:53
  • @Diffy If you're writing a new value, why do you care about the latest value? – Sotirios Delimanolis May 25 '15 at 01:59
  • @SotiriosDelimanolis because if thread A increments the value of i to 1 then i would like thread B to update the value from 1 to 2. Thats why i care about the updated value. – Diffy May 25 '15 at 02:01
  • 3
    @Diffy So you need to **read** the value, potentially check that it's the value you want, and then **write** a new value. That's what `++` does. It's not, as a group, atomic, regardless of `volatile`. – Sotirios Delimanolis May 25 '15 at 02:02
1

Think about what "atomicity" means. It means that two or more operations that happen in one thread appear to happen as an atomic unit as far as other threads can tell.

So if I declare some volatile int foobar, and I write code to perform some operations on it, how would the compiler know which of those operations are supposed to be the atomic unit?

When you write a synchronized block, the atomic unit is whatever you put inside the block.

Solomon Slow
  • 25,130
  • 5
  • 37
  • 57