2012-04-24 2 views
5

У меня есть класс ПунктЭто безопасная публикация объекта?

class Item { 
    public int count; 
    public Item(int count) { 
    this.count = count; 
    } 
} 

Тогда я помещу ссылку на пункт в поле другого класса

class Holder { 
    public Item item; 
    public Holder() { 
    item = new Item(50); 
    } 
} 

Может это нового объекта Item безопасно опубликован? Если нет, то почему? Согласно Java Concurrency in Practice, новый Item опубликован , не будучи полностью сконструированным, но, на мой взгляд, новый Item полностью построен: его ссылка this не исчезает, и ссылка на нее и ее состояние публикуется на том же так что потребительский поток не увидит устаревшего значения. Или это проблема видимости. Я точно не знаю причины.

+0

Интересная статья DW на тему, которая исследует многие проблемы, связанные с синхронизацией: http://www.ibm.com/developerworks/java/library/j-jtp0618/index.html – maksimov

+0

Мне очень жаль, я Забыл! – ohyeahchenzai

ответ

13

Можно ли безопасно опубликовать этот новый предмет предмета? Если нет, то почему?

Проблема связана с оптимизацией и переупорядочением инструкций. Когда у вас есть два потока, которые используют построенный объект без синхронизации, может случиться так, что компилятор решает переупорядочить инструкции ради эффективности и выделить пространство памяти для объекта и сохранить его ссылку в поле itemдо, оно заканчивается с конструктором и инициализацией поля. Или он может переупорядочить синхронизацию памяти, чтобы другие потоки воспринимали так.

Если вы отметили поле item как final, тогда конструктор, как гарантируется, завершит инициализацию этого поля как часть конструктора. В противном случае вам придется синхронизировать блокировку перед ее использованием. Это часть Java language definition.

Вот еще пара ссылок:

+0

Может быть, я должен прочитать спецификацию языка java, спасибо! – ohyeahchenzai

+0

Позвольте мне прямо указывать на правильную [главу.] (Http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4). Это отличное чтение, много больше, чем просто сухая спецификация. –

+0

Спасибо @Marko. Я добавил эту ссылку в свой ответ. – Gray

5

Да, есть проблема видимости, так как Holder.item не final. Таким образом, нет гарантии, что другой поток увидит его инициализированное значение после завершения строительства Holder.

И как отметил @Gray, JVM может свободно изменять порядок инструкций при отсутствии барьеров памяти (которые могут быть созданы блокировкой (синхронизация), final или volatile). В зависимости от контекста вы должны использовать один из них здесь, чтобы обеспечить безопасную публикацию.

+0

Я думаю, что я могу получить ответ, это переупорядочить, но я не точно закажу его, но, как сказал Грей, я знаю кое-что об этом, спасибо вам обоим! – ohyeahchenzai

+0

@ohyeahchenzai Если вы внимательно изучите главу, если JLS упоминается в другом ответе, вам все будет ясно. –

+0

Еще одна веская причина поддержать неизменность, сделав поля окончательными. –

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