Java线程/易失性
我有一个线程:
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()
作为避免易失性的一种聪明方式,但现在我不确定它实际上会按照我的意图做什么。 此外,如果另一个线程调用hibernate()
,哪个线程将进入休眠状态? 我打算让Foo
睡觉,所以如果这不符合我的意图,我会非常欢迎其他建议。
如果另一个线程调用end(),Foo会立即看到活动现在是否为false?
不,它不会。 或者至少,它不会一直看到它。
如果您希望立即run
以便始终看到新值,则分配给该变量的线程与读取该线程的线程之间必须存在“后续”关系。 这可以实现:
active
波动, synchronized
块, AtomicBoolean
或 java.util.concurrent.*
包。 一种避免挥发的聪明方式
声明变量是易变的是确保正确同步的一种方法。 事实上,正确的同步会增加性能开销。 但是,适当的同步对于您的应用程序可靠地工作至关重要,并且避免它是不“聪明”的。
(如果没有正确的同步,你的程序可能大部分时间仍然工作,甚至可能在某些机器上工作,但偶尔也不能工作,实际行为可能取决于你运行程序的机器上,机器负载是什么等等。)
此外,如果另一个线程调用hibernate(),哪个线程将进入休眠状态?
拨打电话的线程将进入睡眠状态。 除非其他线程在相同的Foo对象上执行notify
或notifyAll
,否则它不会唤醒。
如果您只是希望应用程序进入睡眠状态并稍后唤醒,请使用Thread.sleep
。 但请注意,以错误的方式使用sleep
可能会使您的应用程序变得缓慢且无响应。
您的怀疑是正确的:由于active
不是volatile
,因此不能保证run()
会看到另一个线程所做的更改。
一般来说,避免volatile
“巧妙”方式几乎总是一个坏主意。 事实上,即使是volatile
也是你不应该诉诸的。 大多数情况下,坚持使用锁定,监视器或更高级别的同步机制会更安全。
对于第二个问题,将要进入休眠状态的线程是调用hibernate()
的线程。 该线程会一直处于睡眠状态,直到它被中断,虚拟唤醒或其他线程调用Foo
实例监视器上的notify()
/ notifyAll()
。 调用Object#wait()
通常是一个错误,没有用一个循环来检查被等待的条件。
您似乎也对Foo
实例“入睡”的想法感到困惑。 一个Foo
实例不是一个Thread
(或者甚至是一个Runnable
),并且不创建它自己的线程,所以它入睡的想法并没有多大意义。 你可能试图实现的是将线程调用Foo#run()
进入睡眠状态。
关于避免易失性的第一个问题,您应该尝试使用线程中断来指示正在运行的线程停止。
使用另一个线程的interrupt()实例方法来中断正在运行的线程。
在运行的线程中使用isInterrupted()方法来检查中断。
while(!this.isInterrupted()){
//do your work here.
}
不知道为什么要扩展Thread类。 如果在这种情况下实现了Runnable,则应该在运行方法中使用中断来检查中断。 请阅读javadocs以了解关于此方法的一些注意事项。
链接地址: http://www.djcxy.com/p/91963.html下一篇: multimap in .NET