Подтвердить что ты не робот

Java - 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.

4b9b3361

Ответ 1

Да - volatile имеет то же значение для полей ссылочного типа, что и для полей примитивного типа. За исключением того, что в случае ссылочных типов члены объекта, к которому относится поле, также должны быть предназначены для многопоточного доступа.

Ответ 2

Вы можете, и это может быть полезно, но помните, что ключевое слово применяется только к настройке ссылки. Это не влияет на многопоточность видимости свойств внутри этого объекта. Если это состояние, вы, вероятно, захотите синхронизировать каждый доступ к нему в любом случае, чтобы обеспечить необходимые действия перед отношениями.

Ответ 3

Да, ваш код верен. В этом случае сама эта ссылка является изменчивой, поэтому шансы на ссылку автоматически отображаются во всех других потоках, но не на изменения ссылки на объект.

Ответ 4

Если мы посмотрим на класс AtomicInteger, он объявил value как volatile, поэтому его можно использовать в многопоточной среде без какой-либо проблемы с кешем потока.

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 многими потоками; то вам также нужна летучесть для этой справки.

private volatile AtomicInteger reference = new AtomicInteger(0);

В основном это не так; изменится только значение объекта; поэтому объявите его окончательным.

private final AtomicInteger reference = new AtomicInteger(0);