Series About Java Concurrency – Pt. 3
As it seems that even experienced Java programmers might have serious misconceptions regarding the Java memory model, I’ve decided to publish a concurrency related puzzle once again. Consider the following simple program and try to predict it’s output:
package com.wordpress.mlangc.concurrent;
public class PleaseWait
{
private static final long MILLIS_TO_WAIT = 2500;
private static boolean stop = false;
public static void main(String[] args)
{
Thread timer = new Thread(new Runnable()
{
public void run()
{
try
{
Thread.sleep(MILLIS_TO_WAIT);
}
catch(InterruptedException e)
{
// We are already exiting the thread.
}
finally
{
stop = true;
System.out.println("Stop requested.");
}
}
});
timer.start();
long start = System.currentTimeMillis();
while(!stop)
; // <-- Do nothing.
long stoppedAfter = System.currentTimeMillis() - start;
System.out.printf("Stopped after %dms.\n", stoppedAfter);
}
}
The solution, together with explanations will be published in the near future.
Advertisement
Categories: Programming
Concurrency, Java, puzzle
I don’t get it. Doesn’t making the stop variable volatile solve the problem?
Yes, by making the variable volatile we can make sure that the main thread sees the update done by the timer thread in line 24. In it’s current form however, the program might as well loop forever, which is exactly what it does with sun-jdk-1.6.24 when run in server mode.
I ran this on .NET 4.0 – it’s a bit different but still exhibits the same bug:
If you make the stop flag a static member variable in .NET, it always seems to stop regardless of whether or not you make it volatile.
however if you make the methods non-static, and make the stop flag an *instance* variable, then it stops in Debug builds, but release builds only get the “stop requested” and that’s it.
FYI, making it a local variable and using a closure has the same result as an instance variables, as .NET implements closures by simply hoisting “closed-over” variables into instance variables on an auto-generated class.
I take it you have experienced a ‘lost update issue’ somewhere too? (I can’t find your concurrency pt.2! )
Nice blog though, keep it up
Yes, I have in fact experienced a ‘lost update issue’ in real code quite recently. While I was able to fix it quickly, I discovered that this might not have been true for some of my colleagues, which motivated this blog post.
You can find pt. 2 here.