其他线程可以看到继承的非最终字段吗?

时间:2011-08-21 16:07:44

标签: java concurrency visibility

考虑像

这样的第三方类
class A {
    private int value;
    public int getValue() {
        return value;
    }
    public void setValue(int value) {
        this.value = value;
    }
}

我将其变为不可变的

final class ImmutableA extends A {
    public ImmutableA(int value) {
        super.setValue(value);
    }
    public void setValue(int value) {
        throw new UnsupportedOperationException();
    }
}

visibility guarantee for final fields不适用于此处。我的问题是,是否保证其他线程能够看到ImmutableA的正确状态。

如果没有,是否有解决方案?使用委派不是一种选择,因为我需要ImmutableA成为A

3 个答案:

答案 0 :(得分:1)

是的,如果您使用volatile,这可以保证写入对其他线程可见

class A {
    private volatile int value;
    public int getValue() {
        return value;
    }
    public void setValue(int value) {
        this.value = value;
    }
}

答案 1 :(得分:0)

您可以使用synchronized,但这可能会降低吸气速度:

final class ImmutableA extends A 
{
    public ImmutableA(int value) {
        synchronized (this) {
            super.setValue(value);
        }
    }

    public void setValue(int value) {
        throw new UnsupportedOperationException();
    }

    public synchronized int getValue() {
        return super.getValue();
    }
}

答案 2 :(得分:0)

受到starblue的回答的启发,我找到了一种不使用同步的解决方案。它将委托与继承结合起来:

final class ImmutableA extends A {
    private final ImmutableA that;

    public ImmutableA(int value) {
        super.setValue(value);
        that = this;
    }

    public void setValue(int value) {
        throw new UnsupportedOperationException();
    }

    private int superGetValue() {
        return super.getValue();
    }

    public int getValue() {
        return that.superGetValue();
    }
}

我认为它应该有效,因为final可见性保证。但我认为这不值得麻烦。所有方法都需要重写和复制,因为that.getValue()会导致无限递归,that.super.getValue()(或super.that.getValue())是非法的。