17

我不确定 volatile 关键字是否也应该用于非基元。我有一个由一个线程设置/分配并由另一个线程访问的类成员。我应该声明这个成员 volatile 吗?

private /* volatile */ Object o;

public void setMember(Object o) {
    this.o = o;
}

public Object getMember() {
    return o;
}

这里,setMember(...) 由一个线程调用,getMember() 由另一个线程调用。

例如,如果它是一个布尔值,答案是肯定的。

我使用的是 Java 1.4,在这种情况下,该成员是只读的。所以我只关心在这种情况下的可见性,因此我对 volatile 关键字的问题。

4

4 回答 4

11

是的 -volatile对引用类型字段的意义与对原始类型字段的意义完全相同。除了在引用类型的情况下,字段所引用的对象的成员必须设计用于多线程访问。

于 2012-05-15T20:19:28.337 回答
8

您可以,并且可能会有所帮助,但请记住关键字仅适用于参考设置。它对该对象内部属性的多线程可见性没有影响。如果它是有状态的,那么您可能希望围绕对它的每次访问进行同步,以确保所需的先发生关系。

于 2012-05-15T20:19:14.443 回答
4

是的,您的代码是正确的。在这种情况下,引用本身是易失的,因此引用的机会在所有其他线程中自动可见,但不会更改被引用的对象。

于 2012-05-15T20:19:39.367 回答
1

如果我们查找AtomicInteger类,它已声明valuevolatile,因此它可以在多线程环境中使用,而不会出现任何线程缓存问题。

public class AtomicInteger {
    private volatile int value;

    /**
     * Gets the current value.
     *
     * @return the current value
     */
    public final int get() {
        return value;
    }

    /**
     * Sets to the given value.
     *
     * @param newValue the new value
     */
    public final void set(int newValue) {
        value = newValue;
    }

}

但是,如果您认为对 AtomicInteger 的引用,它将被许多线程使用不同的 AtomicInteger 对象修改;那么你也需要 volatile 作为该参考。

private volatile AtomicInteger reference = new AtomicInteger(0);

大多数情况下并非如此。只有对象的值会改变;因此将其声明为最终的。

private final AtomicInteger reference = new AtomicInteger(0);
于 2014-06-17T07:36:59.050 回答