Java线程/ volatile [英] Java threading/volatile

查看:149
本文介绍了Java线程/ 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 立即看到有效现在?具体来说,因为活跃不是 volatile ,我不确定它会不会。我最初创建 end()作为一种避免易失性的聪明方法,但现在我不确定它实际上会按照我的意图行事。
另外,如果另一个线程调用 hibernate(),哪个线程会进入休眠状态?我打算 Foo 睡觉,所以如果这不符合我的意图,我们非常欢迎另一个建议。

解决方案


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


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



如果你想运行总能看到新值立即,分配给变量的线程和读取它的线程之间必须存在后来关系。这可以通过声明活跃 volatile, b $ b

  • 通过在读取和写入变量的语句周围放置 synchronized 块,

  • 使变量变为原子类型;例如 AtomicBoolean ,或

  • 使用其他适当的并发类;参见 java.util.concurrent。* 包。




  • ......一种避免易变的聪明方法...


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



    (如果没有正确的同步,你的程序可能仍会在大部分时间内工作,它甚至可能总是在某些机器上运行。但是,偶尔它不起作用,实际行为可能取决于你运行程序的机器,机器负载是什么,以及其他什么。)


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


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



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


    I have a thread:

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

    If another thread calls end(), will Foo immediately see that active is now false? Specifically, because active isn't volatile, I'm not sure that it will. I initially created end() as a clever way of avoiding volatile, but now I'm unsure that it will actually do what I intend. Additionally, if another thread calls hibernate(), which thread will go to sleep? I'm intending Foo to sleep, so if this doesn't do what I intend, an alternative suggestion would be very welcome.

    解决方案

    If another thread calls end(), will Foo immediately see that active is now false?

    No it won't. Or at least, it won't see it all of the time.

    If you want run to always see the new value immediately, there has to be a "comes after" relationship between the thread assigning to the variable and the thread reading it. This can be achieved:

    • by declaring active volatile,
    • by putting synchronized blocks around the statements that read and write the variable,
    • by making the variable an "atomic" type; e.g. AtomicBoolean, or
    • by using some other appropriate concurrency class; see the java.util.concurrent.* packages.

    ... a clever way of avoiding volatile ...

    Declaring the variable to be volatile is one way of ensuring proper synchronization. It is a fact that proper synchronization imposes a performance overhead. However, proper synchronization is essential for your application to work reliably, and it is NOT "clever" to avoid it.

    (Without proper synchronization, your program will probably still work most of the time, and it might even always work on some machines. However, occasionally it won't work, and the actual behavior is likely to depend on what machine you run the program on, what the machine load is, and other things.)

    Additionally, if another thread calls hibernate(), which thread will go to sleep?

    The thread that makes the call will go to sleep. And it won't wake up unless some other thread does a notify or notifyAll on the same Foo object.

    If you simply want the application to go to sleep and wake up a bit later, use Thread.sleep. But beware that using sleep in the wrong way can make your application slow and unresponsive.

    这篇关于Java线程/ volatile的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆