Небольшое уточнение по ключевому слову volatile

java volatile

58 просмотра

2 ответа

Рассмотрим фрагмент из Java Concurrency на практике

// Unsafe publication
public Holder holder;

public void initialize(){
    holder = new holder(42);
}

public class Holder{
    private int n;

    public Holder(int n) {
        this.n = n;
    }

    public void assertSanity(){
        if (n != n)
            throw new AssertionError("This statement is false.");
    }
}

Одно из решений, предложенных автором книги, -

public static Holder holder = new Holder(42);

И если единственным требованием было предотвращение AssertionError, то это также будет работать нормально.

private final int n;

Мой вопрос - продолжение комментария к этой теме в стеке потока от Джона Винтта.

На самом деле, объявление поля члена изменчивым все еще не гарантирует публикацию до того, как держатель станет видимым. Вы можете взглянуть на закрытый метод ConcurrentHashMap readUnderLock, в котором учитывается этот нюанс. Хотя объявление владельца как изменчивый делает.

Проще говоря, он предлагает 2 вещи:

public volatile Holder holder;

public void initialize(){
    holder = new holder(42);
}

Вышеупомянутое решение будет работать отлично? Если ссылка на объект объявлена ​​как volatile, обеспечивает ли она безопасную публикацию объекта? Массивы тоже объекты. Объявление ссылки на массив не делает его элементы потокобезопасными.

И почему это не будет работать, как это было предложено автором

public class Holder {
private volatile int n;

объявление поля члена изменчивым все еще не гарантирует публикацию до того, как держатель станет видимым

Несмотря на то, что поле члена было объявлено как volatile, оно гарантирует, что условие n != nбудет всегда ложным , и, следовательно, нет AssertionError. Пожалуйста, предложите.

Автор: Shirgill Farhan Источник Размещён: 08.11.2019 11:13

Ответы (2)


2 плюса

Решение

Хотя использование volatileможет помочь, как вы предлагаете, оно не поможет во многих других ситуациях, которые вы можете попытаться использовать. то есть его очень легко использовать volatileнеправильно, поэтому его будет сложно поощрять, если вы не уверены, что знаете, какие операции будут использоваться.

Если ссылка на объект объявлена ​​как volatile, обеспечивает ли она безопасную публикацию объекта?

Это очень зависит от порядка и типа операций. В этом случае напишите

this.n = n;
// and then
holder = ...

Запись, чтобы holderгарантировать, что запись this.nдолжна быть видимой, при условии, что вы также делаете

Holder h = holder; // read barrier
// n must be set.
int n = this.n;

объявление поля члена изменчивым все еще не гарантирует публикацию до того, как держатель станет видимым

Я не согласен в этом случае. После того как вы получили holderв другом потоке, нет никакой вероятности, что при чтении nне будет видно инициализированное значение, когда вы читаете переменную. Это потому, что holderустанавливается только после nинициализации.

Автор: Peter Lawrey Размещён: 20.08.2016 11:13

0 плюса

Попробуй это

public class main {
public volatile static Holder holder;
public static void main(String[] args) {
    // TODO Auto-generated method stub
    // Unsafe publication
    initialize();
    holder.assertSanity(99);
}
public static void initialize(){
    holder = new Holder(42);
}
}

Holder.java

 public class Holder {

 private volatile Integer n;
    public Holder(Integer n) {
        this.n = n;
    }

    public void assertSanity(Integer n){
        if (!((Object)this.n).equals((Object)n))
            throw new AssertionError("This statement is false.");
    }

    public Integer getN() {
        return n;
    }

    public void setN(Integer n) {
        this.n = n;
    }

 }
Автор: Mr. P Размещён: 20.08.2016 11:32
Вопросы из категории :
32x32