繁体   English   中英

Java线程/ volatile

[英]Java threading/volatile

我有一个帖子:

class Foo extends Thread
{
    boolean active = true;

    public void run()
    {
        while(active)
        {
            //do stuff
        }
    }

    public void end()
    {
        active = false;
    }

    public void hibernate()
    {
        synchronized(this)
        {
            wait();
        }
    }
 }

如果另一个线程调用end()Foo立即看到active是否为false 具体来说,因为active不易volatile ,我不确定它会不会。 我最初创建end()作为一种避免volatile的聪明方法,但现在我不确定它实际上会做我想做的事情。 另外,如果另一个线程调用hibernate() ,哪个线程会进入休眠状态? 我打算让Foo睡觉,所以如果这不符合我的意图,那么另一个建议将非常受欢迎。

如果另一个线程调用end(),Foo会立即看到active是否为false?

不,不会。 或者至少,它不会一直看到它。

如果你想让run总是立即看到新值,那么在分配给变量的线程和读取它的线程之间必须存在“后来”关系。 这可以实现:

  • 通过宣布active挥发性,
  • 通过在读取和写入变量的语句周围放置synchronized块,
  • 通过使变量成为“原子”类型; 例如AtomicBoolean ,或
  • 通过使用一些其他适当的并发类; 请参阅java.util.concurrent.*包。

......一种避免不稳定的聪明方法......

将变量声明为volatile是确保正确同步的一种方法。 事实上,正确的同步会带来性能开销。 但是,正确的同步对于您的应用程序可靠地工作至关重要,并且避免它并不“聪明”。

(如果没有适当的同步,你的程序可能仍然可以在大多数时间工作,它甚至可能总是在某些机器上工作。但是,偶尔它将无法工作,实际行为可能取决于你运行程序的机器在什么,机器负载是什么,以及其他东西。)

另外,如果另一个线程调用hibernate(),哪个线程会进入休眠状态?

进行调用的线程将进入休眠状态。 除非某个其他线程在同一个Foo对象上执行notifynotifyAll ,否则它不会被唤醒。

如果您只是希望应用程序进入休眠状态并稍后唤醒,请使用Thread.sleep 但请注意,以错误的方式使用sleep会使您的应用程序变得缓慢且无响应。

你的怀疑是正确的:因为active不是volatile ,所以不能保证run()会看到在另一个线程上做出的更改。

一般来说,避免volatile “聪明”方法几乎总是一个坏主意。 事实上,即使是volatile也是你不应该诉诸的东西。 大多数情况下,坚持使用锁,监视器或更高级别的同步机制更安全。

对于第二个问题,将要进入休眠状态的线程是调用hibernate()的线程。 该线程将一直睡眠,直到它被中断,它会经历虚假的唤醒,或者其他一些线程在Foo实例的监视器上调用notify() / notifyAll() 调用Object#wait()而不用一个检查等待条件的循环来调用它通常是错误的。

你似乎也对 Foo实例“入睡”的想法感到困惑。 Foo实例不是 Thread (甚至是 Runnable ),并且不会创建自己的线程,因此它进入睡眠的想法并没有多大意义。 您可能尝试实现的是将调用 Foo#run()的线程置于休眠状态。

关于避免volatile的第一个问题,您应该尝试使用Thread中断来指示正在运行的线程停止。

使用另一个线程的interrupt()实例方法来中断正在运行的线程。

在正在运行的线程中使用isInterrupted()方法来检查中断。

while(!this.isInterrupted()){
   //do your work here.
}

不确定为什么要扩展Thread类。 如果在这种情况下实现Runnable,则应在run方法中使用interrupt来检查中断。 请阅读javadocs以了解此方法的一些注意事项。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM