开发者

Are inherited non-final fields visible to other threads?

Consider a third-party class like

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

which I make immutable like

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

The visibility guarantee for final fields doesn't apply here. My question is if other threads are guaranteed to see the correct state of ImmutableA.

I开发者_开发技巧f not, is there a solution? Using delegation is not an option since I need ImmutableA to be an A.


yes, if you use volatile this has the guarantee that writes to it are visible to other threads

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


You could use synchronized, though this may slow down the getter:

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();
    }
}


Inspired by starblue's answer I've found a solution using no synchronization. It combines delegation with inheritance:

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();
    }
}

I think it should work because of the final visibility guarantee. But I don't think it's worth the hassle. All methods need to be overridden and duplicated, since that.getValue() would lead to infinite recursion, and that.super.getValue() (or super.that.getValue()) is illegal.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜