1> What is reordering of statements in a single thread.
Ans. Compiler/JVM reorder the statements in a particular thread so that it does not affect the code semantics for single thread execution. For example see the following code.
Scenario 1: Here the order of Line 1 and Line 2 to execute is not at all important. Because they do not depend on one another. So they may be reordered. Now it is very normal that in the main thread the order of execution of the lines are 2,1,3,4.
So output will be
3
true
But the order of execution in the method show() can never be reordered. Because that will change the method semantics. Then the result would be as below
true
3
But this was not the intent of the program. So this would never happen.
Scenario 2: But scenario may be different when two threads act together. Say two threads are started in the main thread. Thread 1 executes method a.example(..) and Thread 2 executes a.show()
Here the execution may very well be in the order as below.
2,3,4,1
Now the output is as below
0
true
That means k is assigned before l.
So this is not exactly what we wanted right?
2> How to stop reordering?
Ans. If the variables k and l are declared as volatile this reordering may be stopped.
Let me rewrite the code again
Think about scenario 2. I repeat here: Thread 1 is executing a.example() and Thread 2 is executing a.show().
Now one possible ordering may be as below
1,3,4,2
Then output is as below
3
False
Here 1 has executed before 2. The reordering has been stopped. Because if the variables are volatile they are accessed in the same order as the code is written.
But did we want this? We needed to see both the values 3 and "True" assigned.
3> How to do this?
Inside the run method of Thread 2 we may add this
Here the lines executed by both the threads will be in following order
1,2,3,4
Also the output will be as follows
3
true
4> Now one tricky question.
Say we have 3 variables j,k and l. I write the class as follws
So if inside the run() method of thread 2 we write as the previous scenario
The result will be ordered. Order of execution will be
1,2,3,4,5,6 and output will be
3
3
true
Here is the question. For the same output can the order of execution be as below?
2,1,3,4,5,6
The answer is "Yes". So j and k must be assigned before l. But it is not necessary that j is assigned before k.
So j and k may be non-volatile. Only l needs to be volatile.
5> What is volatile?
Answer:
1> When a volatile variable is written into memory (assigned some value) it is ensured that all the previous assignments/memory writes in the code in the same thread must occur before this write of the volatile variable.
2> Whenever volatile variable is read it must be read from memory. That's why it may see the value, which has been written just before this read.
3> Whenever they are written they are written to memory rather than local cache of the thread.
There are some other things about volatile. I will come up with them in my next article.
Ans. Compiler/JVM reorder the statements in a particular thread so that it does not affect the code semantics for single thread execution. For example see the following code.
Code:
class A{
private int k = 0;
private boolean l = false;
public void example(int a, boolean b){
k = a;//.... Line 1
l = b;//.... Line 2
}
public void show(){
System.out.println(k);//.... Line 3
System.out.println(l);//.... Line 4
}
public static void main(String args[]){
A a = new A();
a.example(3,"true");
a.show();
}
}
So output will be
3
true
But the order of execution in the method show() can never be reordered. Because that will change the method semantics. Then the result would be as below
true
3
But this was not the intent of the program. So this would never happen.
Scenario 2: But scenario may be different when two threads act together. Say two threads are started in the main thread. Thread 1 executes method a.example(..) and Thread 2 executes a.show()
Here the execution may very well be in the order as below.
2,3,4,1
Now the output is as below
0
true
That means k is assigned before l.
So this is not exactly what we wanted right?
2> How to stop reordering?
Ans. If the variables k and l are declared as volatile this reordering may be stopped.
Let me rewrite the code again
Code:
class A{
private volatile int k = 0;
private volatile boolean l = false;
public boolean getL(){
return l;
}
public void example(int a, boolean b){
k = a;//.... Line 1
l = b;//.... Line 2
}
public void show(){
System.out.println(k);//.... Line 3
System.out.println(l);//.... Line 4
}
public static void main(String args[]){
A a = new A();
//code is omitted.
/*a.example(3,true) is run in thread1*/
/*a.show() is run in thread2*/
}
}
Now one possible ordering may be as below
1,3,4,2
Then output is as below
3
False
Here 1 has executed before 2. The reordering has been stopped. Because if the variables are volatile they are accessed in the same order as the code is written.
But did we want this? We needed to see both the values 3 and "True" assigned.
3> How to do this?
Inside the run method of Thread 2 we may add this
Code:
if(a.getL()){
a.show();
}
1,2,3,4
Also the output will be as follows
3
true
4> Now one tricky question.
Say we have 3 variables j,k and l. I write the class as follws
Code:
class A{
private volatile int j = 0;
private volatile int k = 0;
private volatile boolean l = false;
public void example(int a, boolean b){
j = a;//.... Line 1
k = a;//.... Line 2
l = b;//.... Line 3
}
public boolean getL(){
return l;
}
public void show(){
System.out.println(j)//... Line 4
System.out.println(k);//.... Line 5
System.out.println(l);//.... Line 6
}
public static void main(String args[]){
A a = new A();
//code is omitted.
/*a.example(3,true) is run in thread1*/
/*a.show() is run in thread2*/
}
}
Code:
if(a.getL()){
a.show();
}
1,2,3,4,5,6 and output will be
3
3
true
Here is the question. For the same output can the order of execution be as below?
2,1,3,4,5,6
The answer is "Yes". So j and k must be assigned before l. But it is not necessary that j is assigned before k.
So j and k may be non-volatile. Only l needs to be volatile.
5> What is volatile?
Answer:
1> When a volatile variable is written into memory (assigned some value) it is ensured that all the previous assignments/memory writes in the code in the same thread must occur before this write of the volatile variable.
2> Whenever volatile variable is read it must be read from memory. That's why it may see the value, which has been written just before this read.
3> Whenever they are written they are written to memory rather than local cache of the thread.
There are some other things about volatile. I will come up with them in my next article.