I've been reading up about the use of volatile
variables in Java. I understand that they ensure instant visibility of their latest updates to all the threads running in the system on different cores/processors. However no atomicity of the operations that caused these updates is ensured. I see the following literature being used frequently
A write to a volatile field happens-before every read of that same field .
This is where I am a little confused. Here's a snippet of code which should help me better explain my query.
volatile int x = 0;
volatile int y = 0;
Thread-0: | Thread-1:
|
if (x==1) { | if (y==1) {
return false; | return false;
} else { | } else {
y=1; | x=1;
return true; | return true;
} | }
Since x & y are both volatile
, we have the following happens-before edges
Does this imply that, at any point of time, only one of the threads can be in its 'else' block(since a write would happen before the read)?
It may well be possible that Thread-0 starts, loads x, finds it value as 0 and right before it is about to write y in the else-block, there's a context switch to Thread-1 which loads y finds it value as 0 and thus enters the else-block too. Does volatile
guard against such context switches (seems very unlikely)?
So I think this question is a bit in the weeds, the gist is that volatile
indicates that the value of the variable may change outside the scope of the current thread, and that its value must always be read before use.
In principle, the statement you're quoting is really saying that prior to replacing the value with the current thread, the value will be read.
Your example is a race condition, both threads may return true, neither may return true, or they may each return a different value -- the semantics of volatile
won't define execution for your example (I'd encourage you to compile and run it and see that the output varies).
A common way to illustrate the behavior of volatile
is to run two threads, where one thread updates shared state and to see what happens when the field is marked, and when it isn't:
class VolatileTest implements Runnable
{
// try with and without volatile
private volatile boolean stopRunning = false;
public void triggerStop(){
stopRunning = true;
}
@Override
public void run(){
while(!stopRunning);
System.out.println("Finished.");
}
public static void main (String[] args) throws java.lang.Exception
{
final VolatileTest test = new VolatileTest();
new Thread(test).start();
Thread.sleep(1000);
test.triggerStop() = false;
}
}
In this example, failure to mark stopRunning
as volatile
can lead to the while
loop continuing forever, as unless stopRunning
is marked as volatile
it's not required to read the value on each iteration.
Semantics of Volatile
The problem you are referring to is a variation of Dekker’s Algorithm. With plenty of details on google on different implementations and details regarding it.
If two processes attempt to enter a critical section at the same time, the algorithm will allow only one process in, based on whose turn it is. If one process is already in the critical section, the other process will busy wait for the first process to exit. This is done by the use of two flags, flag[0] and flag[1], which indicate an intention to enter the critical section and a turn variable which indicates who has priority between the two processes.
Wikipedia covers the relevance of volatile
with Dekker's Alogrithm
Volatile Information
But I found this article explains volatile
perfectly in a single sentence.
If a variable is declared as volatile then is guaranteed that any thread which reads the field will see the most recently written value. (Lars Vogel, 2008)
Essentially, volatile is used to indicate that a variable's value will be modified by different threads. (javamex, 2012)
Massey University : Concurrency Volatile Lecture Slide
(source: iforce.co.nz)
Source: Professor Hans W. Guesgen
If you don't yet understand volatile
look into how atomicity
works.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With