Я прочитал в разделе «Java Concurrency In Practice», что «публикация объектов до их полной сборки может поставить под угрозу безопасность потоков». Может ли кто-нибудь объяснить это?Публикация объектов и безопасность потоков
ответ
новому оператору разрешено возвращать значение до завершения конструктора класса. Таким образом, переменная может не читать значение null, но содержит неинициализированный экземпляр класса. Это происходит из-за переупорядочения байтов.
Некоторое разъяснение: С точки зрения одного потока JVM разрешено изменять порядок инструкций. При создании экземпляра традиционно вы могли бы подумать, что идет как это:
- выделить память инициализации
- запуска (конструктор)
- ссылка Присвоить вар
Хотя на самом деле виртуальная машина может сделать что-то вроде:
- выделить память
- правопреемник ссылка на вар
- инициализация запуска (конструктор)
Это имеет преимущество в производительности, так как адреса не должны быть LookUp снова. С точки зрения одного потока это не меняет порядок логики. Программа отлично работает. Но это создает проблему в многопоточном коде. Это означает, что ссылка может быть опубликована до запуска конструктора. Для этого вам необходимо выполнить правило «бывает раньше», чтобы убедиться, что экземпляр полностью инициализирован. Объявление переменных volatile dos обеспечивает соблюдение таких правил - до правил.
Подробнее о переназначения: http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#reordering
Рассмотрим этот код:
public class World{
public static Point _point;
public static void main(String[] args){
new PointMaker().start();
System.out.println(_point);
}
}
public class Point{
private final int _x, _y;
public Point(int x, int y){
_x = x;
World._point = this;//BAD: publish myself before I'm fully constructed
//some long computation here
_y = y;
}
public void toString(){
return _x + "," + _y;
}
}
public class PointMaker extends Thread{
public void run(){
new Point(1, 1);
}
}
Поскольку Point
публикует себя перед установкой значения _y
, вызов println
может уступить "1,0"
вместо ожидаемого "1,1"
.
(Обратите внимание, что он также может дать "null"
если PointMaker
+ Point.<init>
не получают достаточно далеко, чтобы установить World._point
поле перед вызовом println
Исполняет.)
Чтобы быть точным, он может даже напечатать «0,0». Если мы пропустим эту ссылку от конструктора, JLS не сделает никаких гарантий в финале. – Voo
- 1. Массив структурных объектов - Безопасность потоков
- 2. Безопасность нити/публикация
- 3. DefaultTraceListener и безопасность потоков
- 4. Безопасность SharePoint и потоков
- 5. VirtualQuery и безопасность потоков
- 6. Безопасность Java и потоков
- 7. Parallel.ForEach - безопасность потоков с вложенными экземплярами объектов
- 8. Безопасность потоков И статические подклассы
- 9. iBatis SqlMapClient и безопасность потоков
- 10. python WSME и безопасность потоков
- 11. безопасность потоков Java и примитивы
- 12. Конечные поля и безопасность потоков
- 13. итераторы python и безопасность потоков
- 14. STL вектор и безопасность потоков
- 15. Статические методы и безопасность потоков
- 16. Параллельная итерация и безопасность потоков
- 17. Entity Framework DbContext и безопасность потоков
- 18. Неизменность и безопасность потоков в Scala
- 19. CoRegisterClassObject нарушает безопасность потоков
- 20. Безопасность потоков log4net
- 21. Безопасность потоков в Javascript?
- 22. DatagridView VB.Net, безопасность потоков
- 23. Безопасность потоков в wxpython
- 24. Безопасность потоков RijndaelManaged, ICryptoTransform.TransformFinalBlock?
- 25. Безопасность потоков google/dense_hash_map
- 26. Публикация параллельных объектов
- 27. Декларативная безопасность потоков в .NET
- 28. Волатильность и безопасность потоков в Java
- 29. Основные данные, загрузки файлов и безопасность потоков
- 30. C# и безопасность потоков для bool
Не могли бы вы привести источник? – musiKk
@musiKk хороший вопрос, ищется. –
Я бы подумал, что вместо этого ссылка скорее всего будет говорить о публикации объекта внутри конструктора (или того, что он вызывает). Я не могу придумать случай, когда новый оператор возвращает ссылку на объект перед тем, как вызванный конструктор будет завершен. – arcy