Эффективно неизменяемые объекты должны быть безопасно опубликованы
SharedObject
не является неизменным, поэтому не является безопасным.
Если вы хотите, чтобы SharedObject
экземпляров были неизменяемыми, вы должны определить их следующим образом:
class SharedObject {
public final double data;
SharedObject(double data) { this.data = data; }
}
Это гарантирует, что setData
не может произойти ни до, ни после getData
, поэтому нет необходимости распространять изменения в свойстве внутренних данных между потоками.
1) Является ли это решение "безопасным" для моих нужд? (потребители смогут прочитать новейшее значение ссылки SharedObject и его данные внутри, значения могут быть потеряны между ними)
volatile
на общем объекте владельца должен означать, что holder.sharedObject
всегда актуален при чтении.
3) Если мы заботимся только о новейших снимках объекта, означает ли это, что у нас может быть несколько производителей?
Слово «новейший» подразумевает некоторый смысл «случается раньше» - потребитель не видит производства ценностей, которые произошли до производства новейшей стоимости. Где это применяется?
EDIT:
Ok. Я думаю, что я понимаю проблему сейчас. Вы полагаетесь на volatile
, чтобы представить не только правильный объект, но и правильный вид объекта. Это действительно в Java 5 и более поздних версиях, но не ранее.
С http://www.javamex.com/tutorials/synchronization_volatile_java_5.shtml
Начиная с Java 5, доступ к энергозависимой переменной создает барьер памяти: он эффективно синхронизирует все кэшированные копии переменных с основной памятью, как вход или выход из синхронизированного блока, который синхронизируется с данным объектом. Как правило, это не оказывает большого влияния на программиста, хотя иногда делает volatile хорошим вариантом для безопасной публикации объектов .
Таким образом, поскольку поле, содержащее ссылку на SharedObject
, является изменчивым, потребитель всегда будет видеть самое последнее (для некоторого определения) значение, хранящееся в SharedObject
.
Кажется, это соответствует требованиям, которые вы изложили.
Таким образом, в Java 4 и раньше это, вероятно, работало бы - до тех пор, пока SharedObject
содержит поле из одного слова (не double
с или long
с), а в Java 5 и более поздних, где двойное слово проблема исправлена, вы солидны.