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

时间:2015-05-29 15:14:10

标签: java multithreading for-loop while-loop synchronized

以下代码可以使用,但我稍微不得不编写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;
    }
}

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

for (;running;) {}

if (running) {}

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

3 个答案:

答案 0 :(得分:3)

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

然而,如果你需要多次启动和停止,这不会起作用。这是因为易失性字段"可能会错过更新"

这里有一个链接,说明volatilelink

之类的情况下的工作时间

这里是来自该链接的代码示例,因为它已经死了:

public class StoppableTask extends Thread {
   private volatile boolean pleaseStop;

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

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

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

答案 1 :(得分:2)

您可以将运行字段设置为volatile。使字段变为volatile会使JVM注意到它应该对其他线程可见的该字段进行更改。 "错过更新"警告是针对您想要读取值并根据该值更新的情况,这在这里似乎不适用。 多个线程可以写入此字段,如果他们所做的只是设置一个布尔标志,那么这不会成为问题。

或者,如果您尝试取消某个帖子,那么Thread上已经提供了一个等效标志(并且可以解决可见性问题)。您可以在线程上调用中断,Runnable中的代码可以查询Thread.currentThread().isInterrupted()以判断它是否被中断。这比使用自己的标志更可取,因为中断将导致线程在等待或休眠时唤醒。有了自己的旗帜,你必须等到控制到达可以测试旗帜的地方。

答案 2 :(得分:0)

只是为了补充其他人提出的建议Repeater。 或者,您可以为检查创建一个类。 我已将变量设为volatile,因此所有线程都将指向同一对象。

static

注意:

如果您不需要全局变量,请删除class Runner{ boolean static running=true; public static synchronized boolean getRunning(){ return running; } public static synchronized boolean setRunning(boolean r){ running=r; } }