java 我可以同步读取控制变量吗?




multithreading for-loop (3)

下面的代码可以工作,但是我有点反感不得不写下isRunning()方法:

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;
    }
}

我可以以其他方式同步while (running){}running变量的读取,还是必须编写isRunning()方法? 同样的问题也适用于其他控制变量,例如

for (;running;) {}

要么

if (running) {}

在所有这些情况下,似乎你被迫写一个毫无意义的方法来使同步正确。 我错过了什么吗?


只是加起来,其他人的回答显示volatile 。 或者,你可以创建一个类的检查。 我已经使变量是static ,所以所有的线程将指向同一个对象。

class Runner{

 boolean static running=true;

 public static synchronized boolean getRunning(){
     return running;
 }

 public static synchronized boolean setRunning(boolean r){
     running=r;
 }
}

注意:

如果您不需要全局变量,则删除static


如果您只重置一次running的值以指定停止,则可以使用volatile关键字。

但是,如果你需要多次启动和停止,这将不起作用。 这是因为易变的字段“可能会错过更新”

这里有一个链接,以解释什么时候这种链接的情况下volatile作品

这是从链接的代码示例,因为它死了:

public class StoppableTask extends Thread {
   private volatile boolean pleaseStop;

   public void run() {
     while (!pleaseStop) {
       // do some stuff...
     }
   }

  public void tellMeToStop() {
     pleaseStop = true;
   }
  }

如果需要多次启动和停止,则需要使用Java 5并发锁对象之一或显式同步


你可以使运行领域变得不稳定。 让字段变成易变的,让JVM注意到它应该改变这个字段对其他线程可见。 “错过更新”的警告是你想读取一个值并根据该值进行更新的情况,这在这里似乎不适用。 多线程可以写入这个领域,如果他们正在做的是设置一个布尔标志,那么这不会是一个问题。

或者,如果您尝试取消某个线程,则线程上已经提供了一个等效的标志(可见性问题已得到解决)。 你可以在一个线程上调用中断,Runnable中的代码可以查询Thread.currentThread().isInterrupted()以告知是否被中断。 这比使用自己的标志更好,因为中断会导致线程在等待或睡眠时唤醒。 用自己的国旗,你必须等到控制权到达可以测试国旗的地方。





synchronized