Видны ли унаследованные не финальные поля другим потокам? - PullRequest
1 голос
/ 21 августа 2011

Рассмотрим сторонний класс, такой как

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

Гарантия видимости для конечных полей здесь не применима,Мой вопрос заключается в том, гарантируют ли другие потоки правильное состояние ImmutableA.

Если нет, есть ли решение?Использование делегирования не вариант, так как мне нужно, чтобы ImmutableA был A.

Ответы [ 3 ]

1 голос
/ 21 августа 2011

да, если вы используете volatile, это гарантирует, что записи в него видны другим потокам

class A {
    private volatile int value;
    public int getValue() {
        return value;
    }
    public void setValue(int value) {
        this.value = value;
    }
}
0 голосов
/ 22 августа 2011

Вдохновленный ответом 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()) недопустимо.

0 голосов
/ 21 августа 2011

Вы можете использовать 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();
    }
}
...