I tried to reproduce the non-volatile variable behavior in Java multi-threading.
Here I have non-volatile variable test
in OccurrenceCounter.java class.
In ThreadDemo.java class I have main
method that spawns two threads.
In thread1
it continuously check the value of non-volatile variable test
in while loop.
If I run below example in MyRunnableThread1.java the value of occurrenceCounter.isTest()
is not taken from CPU cache.
OccurrenceCounter.java:
public class OccurrenceCounter {
// non-volatile variable
private boolean test=true;
public OccurrenceCounter(boolean test)
{
this.test=test;
}
public boolean isTest() {
return test;
}
public void setTest(boolean test) {
this.test = test;
}
}
MyRunnableThread1.java:
// Thread 1
public class MyRunnableThread1 implements Runnable {
private String threadName;
private OccurrenceCounter occurrenceCounter;
public MyRunnableThread1(String threadName,OccurrenceCounter occurrenceCounter)
{
this.threadName=threadName;
this.occurrenceCounter=occurrenceCounter;
}
@Override
public void run() {
System.out.println("Thread "+threadName + " started");
System.out.println("value of flag:"+occurrenceCounter.isTest());
int i=0;
// random processing code
while(i<1000000000L)
{
i++;
i++;
i++;
}
// checking whether non-volatile variable is taken from cpu cache
while(occurrenceCounter.isTest())
{
}
System.out.println("Thread "+threadName + " finished");
}
}
MyRunnableThread2.java:
// Thread 2
public class MyRunnableThread2 implements Runnable {
private String threadName;
private OccurrenceCounter occurrenceCounter;
public MyRunnableThread2(String threadName,OccurrenceCounter occurrenceCounter)
{
this.threadName=threadName;
this.occurrenceCounter=occurrenceCounter;
}
@Override
public void run() {
System.out.println("Thread "+threadName + " started");
occurrenceCounter.setTest(false);
System.out.println("Thread "+threadName + " finished");
}
}
ThreadDemo.java:
public class ThreadDemo {
public static void main(final String[] arguments) throws InterruptedException {
System.out.println("main thread started");
OccurrenceCounter occurrenceCounter =new OccurrenceCounter(true);
MyRunnableThread1 myRunnableThread1=new MyRunnableThread1("Thread1", occurrenceCounter);
MyRunnableThread2 myRunnableThread2=new MyRunnableThread2("Thread2", occurrenceCounter);
Thread t1=new Thread(myRunnableThread1);
Thread t2=new Thread(myRunnableThread2);
t1.start();
try
{
Thread.sleep(100);
}
catch(Exception e)
{
System.out.println("main thread sleep exception:"+e);
}
t2.start();
System.out.println("main thread finished");
}
}
Here in MyRunnableThread1.java in while loop the the condition occurrenceCounter.isTest()
is not returned from CPU cache even though test
variable in OcuurenceCounter
class is non-volatile.
But if I remove the first while loop:
while(i<1000000000L)
{
i++;
i++;
i++;
}
Then I can see that the condition occurrenceCounter.isTest()
is always false even though it is update by thread2
and thread1
never terminates.
So why this while loop:
while(i<1000000000L)
{
i++;
i++;
i++;
}
Impacting the behavior of non-volatile variable?
Is this first while loop forcing anyway to read value from memory instead of from CPU cache in of thread1
? I tried to get answer for this a lot. But I couldn't.
Please anyone help me to figure this out.