The outline of the program:
We have two threads (t1
and t2
) that write an integer value, then flush the written value to RAM.
Another thread (t3
) checks whether the value coincidences with the one written by t1
or t2
, and if not, prints it.
public class Container
{
int a;
volatile boolean b;
public static void main(String[] args)
{
Container container = new Container();
Thread t1 = new Thread()
{
@Override
public void run()
{
for (;;)
{
container.a = 409;
container.b ^= container.b;
}
}
};
Thread t2 = new Thread()
{
@Override
public void run()
{
for (;;)
{
container.a = 102;
container.b ^= container.b;
}
}
};
Thread t3 = new Thread()
{
@Override
public void run()
{
try
{
Thread.sleep(100);
} catch (InterruptedException e)
{
e.printStackTrace();
}
for (;;)
{
if (container.a != 409 && container.a != 102 )
System.out.println(container.a);
}
}
};
t1.start();
t2.start();
t3.start();
}
}
What I thought would happen:
Since a
isn't volatile
, I thought t3
would cache a
and just never print anything.
What actually happens:
For a second or so (no matter long you let t3
sleep), it prints in rapid succession either 102 or 409. Then, printing stops (forever).
What exactly happens here?
container.a
not being volatile doesn't mean it's mandatorily cached by t3
. All it means is that there are no guarantees whether it will be or not.
The reason it is free to print any value is the time-of-check-to-time-of-use problem here:
if (container.a != 409 && container.a != 102 )
System.out.println(container.a);
As for why this exact behaviour on the exact environment you tested it in, we can only guess. But my money would be on the theory that while the code is run as interpreted, it will go and read container.a
every time, but once it's compiled to native code by Hotspot, the value is only loaded into a register once, and that's the end of it. You can verify this hypothesis by using the -XX:+PrintCompilation
command line flag.
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