2017-02-05 11 views
0

Я читаю параллелизм на практике и имею некоторое недоразумение.
цитата:Двойная проверка-блокировка гарантирует состояние объекта? (параллелизм на практике)

реальная проблема с DCL является предположение о том, что самое худшее, что может произойти при чтении ссылку на общий объект без синхронизации является ошибочно видеть несвежий значение (в данном случае, нуль) ; в этом cse идиома DCL компенсирует этот риск, снова попробовав с заблокированным замком. Но худший случай на самом деле значительно неправильный - можно увидеть текущее значение ссылки, но занесенные значения для состояний объекта, что означает, что объект может быть замечен как недопустимое или неправильное состояние.

после Брайан Гетц пишет, что DCL будет работать в текущей модели памяти, используя летучий:

public class DoubleCheckLociing{ 

    private static volatile Resource resource; 

    public static Resource getInstance(){ 
     if(resource == null){ 
      synchronized(DoubleCheckLociing.class){ 
       if(resource == null){ 
        resource = new Resource(); 
       } 
      } 
     } 
     return resource; 
    } 
} 

Я не уверен, если понимать фразу о состоянии правильной.

Давайте представим, что Resource класс выглядит следующим образом:

class Resource{ 
    private Date date = new Date();//mutable thread unsafe class 
    private int k = 10; 

    public Date getDate(){ 
     return date; 
    } 

    public int getK(){ 
     return k; 
    } 

} 

Есть ли у меня гарантии, что getInstance всегда возвращают correct ресурс, который всегда возвращает правильный k (10) и date?

+0

* Есть ли у меня гарантии, что getInstance всегда возвращает правильный ресурс, который всегда возвращает правильные k (10) и дату? *. Поэтому вам просто нужно подтвердить, правильно ли Брайан Гетц *? – CKing

+0

Мне нужно подтверждение, что мое понимание правильное. Мое прежнее понимание было совсем другим. Я думал, что проблема с 2 чтениями общей ссылки. Первый может вернуться! = Nul, но второй может быть пустым – gstackoverflow

+0

И вы не нашли ни одного ответа на сайте, который подтвердил это? – CKing

ответ

3

С volatile на месте у вас есть эти гарантии. Без volatile вы этого не сделаете.

Когда один поток записывает изменчивую переменную resource, операция включает в себя «барьер памяти», который гарантирует, что все, что он написал до этого, подобно инициализации полей экземпляра, сначала записывается в системную память.

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

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

0

Есть ли у меня гарантии, что getInstance всегда возвращает правильный ресурс, который всегда возвращает правильные k (10) и дату?

Да и нет. Как указывает @Matt, если поле volatile, то вам гарантировано, что все поля Resource будут опубликованы соответствующим образом, когда к нему обратится другой поток, который является важной частью примера двойной проверки-блокировки. Защитные барьеры volatile обеспечивают это.

Однако, ваш Resource содержит нефинальные поля, которые могут быть изменчивыми (если был установлен метод setter или нет).Если вы сделаете свои поля final, то на самом деле вы можете обойтись без volatile, потому что поля final будут опубликованы после публикации ссылки на ваш Resource.

private final Date date = new Date(); 
private final int k = 10; 

Как вы упоминаете, однако, это не в полной мере сохранить вас, потому что Date также изменчиво. Вы должны убедиться, что ваш код (или другой код) не вызывает никаких методов setter в поле date, тогда вы будете в порядке.

Это хороший пример того, насколько важно отслеживать изменчивость в поточных программах.

+0

Но если я не выполняю маты моих объектов, у меня есть гарантии увидеть значения, которые я установил в конструкторе (inline в моем случае) – gstackoverflow

+0

Если они окончательные, да. Если они не являются окончательными, то «volatile» дает вам эти гарантии, да @gstackoverflow. – Gray