Can I synchronize the reading of control variables?
The following code will work, but I am a bit reluctant to write the isRunning () method:
class Test {
private boolean running;
public void startX() {
synchronized(this) {
running = true
}
while (isRunning()) {
//do something
}
}
public synchronized void stopX() {
running = false;
}
private synchronized boolean isRunning() {
return running;
}
}
Is it possible to synchronize the reading of the variable running
in while (running){}
some other way or do I need to write the isRunning () method? The same question applies to other control variables as well, such as
for (;running;) {}
or
if (running) {}
In all these cases, it seems that you are forced to write a meaningless method to synchronize correctly. Did I miss something?
source to share
if you only reset the value running
once to assign a stop, you can use the keyword volatile
.
However, if you have to start and stop multiple times, this won't work. This is because volatile fields "may miss update"
Here's a link to explain when it volatile
works in cases like the link
here is some sample code from that link if dead:
public class StoppableTask extends Thread {
private volatile boolean pleaseStop;
public void run() {
while (!pleaseStop) {
// do some stuff...
}
}
public void tellMeToStop() {
pleaseStop = true;
}
}
If you need to start and stop many times, you need to either use one of the Java 5 concurrent locking objects or explicit synchronization
source to share
You can make the current field mutable. Making a volatile field puts the JVM on notice that it should make changes to that field visible to other threads. The "skip update" caveat is for cases where you want to read a value and update based on that value, which is not possible here. Multiple threads can write to this field, if all they are doing is setting a boolean flag, then this won't be a problem.
Alternatively, if you are trying to cancel a thread, there is already an equivalent flag for Thread for that (and the visibility issue will be taken care of). You can call an interrupt on a thread, the code in Runnable can query Thread.currentThread().isInterrupted()
to determine if it was interrupted. This is preferable to using your own flag, because interrupting will cause the thread to wake up if it waits or sleeps. With your own flag, you need to wait until the control reaches where the flag can be checked.
source to share
just to add to other people the answer that suggested volatile
. Alternatively, you can create a class for checks. I made the variable equal static
, so all threads will point to the same object.
class Runner{
boolean static running=true;
public static synchronized boolean getRunning(){
return running;
}
public static synchronized boolean setRunning(boolean r){
running=r;
}
}
Note:
if you don't require a global variable then remove static
source to share