Java线程/易失性
我有一根线:Java线程/易失性,java,multithreading,volatile,Java,Multithreading,Volatile,我有一根线: class Foo extends Thread { boolean active = true; public void run() { while(active) { //do stuff } } public void end() { active = false; } public void hibernate()
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
会立即看到处于活动状态
现在是false
?具体来说,因为活动
不是易失性
,所以我不确定它是否会。我最初创建了end()
,作为一种避免volatile的聪明方法,但现在我不确定它是否真的能达到我的目的。
另外,如果另一个线程调用
hibernate()
,哪个线程将进入睡眠状态?我打算睡Foo
,因此如果这不符合我的意愿,那么另一个建议将是非常受欢迎的。你的怀疑是正确的:因为活动的不是易变的
,所以不能保证运行()
会在另一个线程上看到所做的更改
一般来说,避免波动的“聪明”方法几乎总是个坏主意。事实上,即使是volatile
,您也不应该求助于它。大多数情况下,使用锁、监视器或更高级别的同步机制更安全
对于第二个问题,将进入睡眠状态的线程是一个名为hibernate()
的线程。该线程将一直处于休眠状态,直到被中断、经历虚假唤醒,或在实例的监视器上执行其他一些线程调用notify()
/notifyAll()
。调用对象35; wait()
而不使用循环检查等待的条件通常是错误的
您似乎还对Foo
实例“进入睡眠”的概念感到困惑。Foo
实例不是线程(甚至不是Runnable
),也不会创建自己的线程,因此它进入睡眠状态的想法没有多大意义。您可能试图实现的是将调用Foo#run()
的线程置于睡眠状态
如果另一个线程调用end(),Foo会立即看到active现在为false吗
不会的。或者至少,它不会一直看到它
如果希望run
始终立即看到新值,则在分配给变量的线程和读取变量的线程之间必须存在“后面来”关系。这可以通过以下方式实现:
- 通过声明
active
volatile
- 通过在读写变量的语句周围放置
synchronized
块
- 通过使变量成为“原子”类型;e、 g.
原子布尔
,或
- 通过使用其他适当的并发类;请参阅
java.util.concurrent.*
包
。。。一个避免波动的聪明方法
将变量声明为volatile是确保正确同步的一种方法。事实上,适当的同步会带来性能开销。然而,适当的同步对于应用程序可靠地工作是必不可少的,避免同步并不是“聪明”的
(如果没有适当的同步,您的程序可能大部分时间仍能工作,甚至可能在某些机器上始终能工作。但是,有时它会不工作,实际行为可能取决于您运行程序的机器、机器负载以及其他因素。)
另外,如果另一个线程调用hibernate(),哪个线程将进入睡眠状态
发出呼叫的线程将进入睡眠状态。除非其他线程对同一个Foo对象执行notify
或notifyAll
,否则它不会被唤醒
如果您只是想让应用程序进入睡眠状态并稍晚醒来,请使用Thread.sleep
。但是要注意,以错误的方式使用sleep
会使应用程序运行缓慢且无响应。关于避免volatile的第一个问题,您应该尝试使用线程中断来通知正在运行的线程停止
使用另一个线程的实例方法中断正在运行的线程
在运行线程中使用方法检查中断
while(!this.isInterrupted()){
//do your work here.
}
不确定为什么要扩展线程类。如果在这种情况下实现了Runnable,那么应该在run方法中使用来检查中断。请阅读javadocs以了解此方法的一些注意事项 Re:Foo与Foo的一个实例,我知道两者的区别。我只是不想写Foo bar=new Foo();bar.start();问我所有关于酒吧的问题。我不是指Foo
类和它的一个实例之间的区别;我指的是你的Foo
类没有扩展Thread
,因此它本身不是一个线程。。。我意识到有人/不知何故/某个地方没有(大时间)解释说,在几乎所有的硬件上,易失性读取都是便宜的。volatile只是确保了有序语义,volatile read只是一种有序读取,从技术上讲可能会阻止CPU进行某些优化(即无序加载),但您永远不应该在意。易失性写操作成本更高,因为它们需要刷新所有写操作(缓存线),但易失性写操作通常也很少见。