2016-10-27 7 views
2

Java Параллелизм на практике имеет следующий пример:Понимание JVM гарантии неизменных объектов

@ThreadSafe 
public class VolatileCachedFactorizer implements Servlet { 
    private volatile OneValueCache cache = new OneValueCache(null, null); 

    public void service(ServletRequest req, ServletResponse resp) { 
     BigInteger i = extractFromRequest(req); 
     BigInteger[] factors = cache.getFactors(i); 
     if (factors == null) { 
      factors = factor(i); 
      cache = new OneValueCache(i, factors); 
     } 
      encodeIntoResponse(resp, factors); 
     } 
    } 
} 

OneValueCache является непреложным.

Из того, что я понимаю, используя volatile, обеспечивается, чтобы все потоки отображали актуальную ссылку, хранящуюся в переменной cache.

В то же время он говорит, что

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

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

JLS также имеет следующий пример:

class FinalFieldExample { 
    final int x; 
    int y; 

    static FinalFieldExample f; 

    public FinalFieldExample() { 
     x = 3; 
     y = 4; 
    } 

    static void writer() { 
     f = new FinalFieldExample(); 
    } 

    static void reader() { 
     if (f != null) { 
      int i = f.x; // guaranteed to see 3 
      int j = f.y; // could see 0 
     } 
    } 
} 

Они не используют volatile для поля f. Разве это не означает, что другие потоки могут видеть f как null и никогда не видеть созданный экземпляр?

Может ли кто-нибудь объяснить?

+2

Объект неизменен, переменная нет. – OrangeDog

+1

Вы объединяете две очень разные вещи: - Объект, если он обозначен как неизменный, является потокобезопасным. - переменная (относящаяся к объекту) открыта для указания на любой другой объект, поэтому потребность в ключевом слове 'volatile' для обеспечения того, чтобы какой-либо компонент использовал переменную, имеет доступ к последней копии того, что относится к переменной to – kolossus

+0

Что меня смутило: «Неизменяемые объекты могут быть опубликованы с помощью любого механизма». Назначение переменной - это механизм, но это не было бы поточно-безопасным для этого, верно? – damluar

ответ

2

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

Это верно, но это понятие относится к переменной, а инструкция цитировал JCiP

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

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

Неизменяемые объекты могут быть опубликованы с помощью любого механизма.

В настоящее время в отношении Вашего второго примера:

Разве это не означает, что другие потоки могут видеть е утратившим никогда не увидеть созданный экземпляр?

Это право.Если один поток вызывает writer() другой нитевидный могут видеть f в null или f.y в 0, потому что он не уважает безопасной публикации:

3.5.3. Safe Publication Idioms

Чтобы опубликовать объект безопасно, как ссылка на объект, так и состояние объекта должны быть видимыми для других потоков одновременно. Правильно построенный объект можно безопасно опубликовать:

  • Инициализация ссылки на объект из статического инициализатора;
  • Хранение ссылки на него в поле volatile или AtomicReference;
  • Сохранение ссылки на него в конечном поле правильно сконструированного объекта; или
  • Хранение ссылки на него в поле, которое должным образом защищено блокировкой.
+0

'может быть опубликован через любой механизм'. Не присваивает переменной 'cache' механизм публикации? – damluar

+0

Да, это так. Вы ссылаетесь на мое утверждение, что оно «не относится к переменной, а относится к самому объекту»? Это было в отношении «Неизменяемых объектов можно безопасно использовать». – dudel

Смежные вопросы