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?

+3


source to share


3 answers


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

+3


source


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.

+2


source


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

0


source







All Articles