请考虑以下代码:
class Foo {
java.util.Timer timer = new java.util.Timer();
void doAction() {
...
timer.schedule(new SomeTimerTask(), 0L);
...
}
void cancelAction() {
timer.cancel();
}
}
从不同的线程调用方法。首先调用方法doAction()。
我应该声明timer
字段volatile
对另一个帖子可见吗?
答案 0 :(得分:6)
最好在synchronized
和doAction()
这样的方法上使用cacelAction()
关键字操纵实例变量的关键状态 timer
。
volatile
关键字的作用与您为每个线程反映volatile字段的描述非常相似,但仅适用于每个单独的操作,而不适用于所有操作。
答案 1 :(得分:3)
您不需要使字段变为volatile,因为两个线程都不会对字段本身进行更改:其值在初始化程序中设置一次,并且在此之后不会更改。
您可能需要向方法添加同步,但在这种情况下完全不需要声明变量volatile
:使用final
会更合适。
答案 2 :(得分:2)
Timer类根据其javadoc,
是线程安全的因此,将timer
声明为volatile
就足够了。
但是,如果未将timer
分配给其他任何地方(如图所示),更好的解决方案就是将该字段声明为final
。这足以确保可以从多个线程安全地使用timer
变量而无需进一步同步。 (JLS Section 17.5特别保证这一点。)
如果Timer不是线程安全的,那么您需要在同步方法或块(或使用Locks等实现的等效方法)上对Timer实例执行所有操作。将timer
声明为volatile
或final
是不够的。
答案 3 :(得分:0)
即使没有将字段声明为volatile,它也会对所有线程都可见。与变量关联的volatile
关键字将指示java运行时此变量可能被多个线程修改,因此不应在本地缓存。
答案 4 :(得分:0)
不需要将字段设为volatile
,但最好使用synchronized
方法。
public void synchronized doAction(){}
public void synchronized cancelAction(){}