我应该声明字段volatile吗?

时间:2012-09-05 10:33:09

标签: java concurrency reference volatile

请考虑以下代码:

class Foo {
    java.util.Timer timer = new java.util.Timer();

    void doAction() {
        ...
        timer.schedule(new SomeTimerTask(), 0L);
        ...
    }

    void cancelAction() {
        timer.cancel();
    }
}

从不同的线程调用方法。首先调用方法doAction()。

我应该声明timer字段volatile对另一个帖子可见吗?

5 个答案:

答案 0 :(得分:6)

最好在synchronizeddoAction()这样的方法上使用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声明为volatilefinal是不够的。

答案 3 :(得分:0)

即使没有将字段声明为volatile,它也会对所有线程都可见。与变量关联的volatile关键字将指示java运行时此变量可能被多个线程修改,因此不应在本地缓存。

答案 4 :(得分:0)

不需要将字段设为volatile,但最好使用synchronized方法。

public void synchronized doAction(){}

public void synchronized cancelAction(){}