2015-05-29 70 views
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) {} 

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

+2

只是让''running' volatile'。 –

回答

2

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

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

3

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

但是,如果您需要多次启动和停止,这将不起作用。这是因为挥发性场“可能会错过更新”

下面就来解释一个链接时volatile作品在类似案例link

这里是从该链接的代码示例柜面它会死:

public class StoppableTask extends Thread { 
    private volatile boolean pleaseStop; 

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

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

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

+0

感谢您的回答。不幸的是,我不能保证只有一个线程会写入这个值,所以它必须同步AFAIK – user1675642

+0

@ user1675642'volatile'保证了不同线程之间的可见性,因此对于这种没有问题的特殊情况。考虑到在执行过程中写入'pleaseStop'将始终为真,因此不会有更新未命中的机会。 –

+0

@ E_net4'pleaseStop'来自我链接到的代码示例博客。如果他们的'startX()'被再次调用,OP可能会将标志置位。 – dkatzel

0

只需加上其他人的答案即可取笑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

+0

我可以永远不会批准使用波动字段的全局监视器同步。 –

+0

@ E_net4它是一个意见交换的问题。我有一个包含超过1000个线程的程序,运行的行为相同。迄今没有发生灾难性事件。 – nafas

+0

不改变它不是可扩展解决方案的事实。使它变为静态意味着你甚至不能创建它的多个实例。 –

相关问题