0

In the graphic class I have it so when you press "m" it make a boolean M true, and then I have this piece of code.

graphic.m = false;
while(graphic.m == false){
}
graphic.m = false;

It won't work, it does not continue the code ahead of it.

But if I do this

graphic.m = false;
while(graphic.m == false){
System.out.println("m");
}
graphic.m = false;

It works prefectly, can someone explain why and how to get past this?

CalebB
  • 470
  • 1
  • 4
  • 11

2 Answers2

3

For this to ever work, some other thread must be setting graphic.m to true. So I'll assume that's happening.

My guess is that graphic.m is not a volatile field. That means that there's no formal happens-before relationship between one thread writing to it (setting it to true from the other thread) and another thread reading from it (the code you have). The JVM is free to cache values within the thread (or let the CPU cores cache them, etc), and seems to be doing so.

System.out.println is a synchronized method, though. Even though this doesn't have any formal affect on graphic.m according to the JLS, it's very possible that the act of releasing/acquiring that synchronization lock would flush memory across cores such that your thread happens to see graphic.m's latest value. To emphasize: this doesn't have to happen by the Java spec, and you shouldn't rely on that behavior -- if you do, you're likely to be bitten by a hard-to-catch bug in some future version of the JVM, or some slightly different hardware, etc.

The solution would be to make graphic.m a volatile field (or get/set it via a synchronized method, or use an AtomicBoolean).

yshavit
  • 42,327
  • 7
  • 87
  • 124
0

You need to include the volatile keyword to guarantee visibility of changes of your variable across threads.

When threads operate on non-volatile variables, each one likely copies those variables from main memory into its own CPU cache while working on them. For non-volatile variable, the JVM doesn't guarantee that it will read data from main memory or a CPU cache, or that it will write from the CPU cache back to main memory.

If you declare a variable volatile, the JVM ensures that all reads will be from main memory, and all writes will be to main memory, too.

System.out is likely helping to flush across your CPUs caches. It's a synchronized method, so I'm thinking its lock will give the JVM time to do this.

Keith
  • 3,079
  • 2
  • 17
  • 26