maaartinus
maaartinus

Reputation: 46482

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.

If not, is there a solution? Using delegation is not an option since I need ImmutableA to be an A.

Upvotes: 1

Views: 100

Answers (3)

maaartinus
maaartinus

Reputation: 46482

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.

Upvotes: 0

starblue
starblue

Reputation: 56812

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

Upvotes: 0

ratchet freak
ratchet freak

Reputation: 48216

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

Upvotes: 1

Related Questions