Моя логика заключается в том, что, поскольку я создаю объект класса A внутри метода класса B, он создается в стеке, а не в куче, и, следовательно, он безопасен для потоков.
Вашлогика и / или терминология не верны.На самом деле, экземпляр ClassA
находится в куче.Все обычные объекты Java создаются в куче!
Ваш код на самом деле поточно-ориентирован , но правильное объяснение выглядит следующим образом:
- Объектсоздан, и единственная ссылка на него назначена локальной переменной.
- При проверке ни один другой поток не может увидеть эту переменную.
- При проверке ссылка на объект никогда не передается другойнить;то есть это не опубликовано .
- Точки 1., 2. и 3. означают, что объект ограничен потоком 1 дляего полное время жизни.
- Поскольку объект ограничен потоком, нет необходимости учитывать безопасность потоков.
Недостаточно сказать (просто), чтоиспользуется локальная переменная:
Существуют сценарии, в которых другой поток может видеть значение локальной переменной;например, если лямбда или закрытие внутреннего метода создано и передано другому потоку.
Также необходимо учитывать, что значение в переменной может быть передано другому потоку.
Финализация и обработка ссылок будут выполняться в другом потоке.Однако это НЕ должно представлять проблему безопасности потока.(Спецификация JLS заботится о финализации, а javadoc для Reference
заботится о ссылках. В обоих случаях происходит до в соответствующих точках.)
1 - Это причудливый способ сказать, что никакой другой поток никогда не сможет увидеть объект и его ссылку.
Вы имеете в виду, что classA является потокобезопаснымсам?
Нет.Это не потокобезопасный сам по себе.Это потокобезопасно в этом конкретном контексте.Или, более того, безопасность потока в данном контексте является спорным вопросом ... потому что экземпляр ограничен потоком.
Разве я не должен определять класс как потокобезопасный во всех контекстах?Я не знаю, как завтра это может быть использовано?
Это зависит от вас!
Но учтите следующее: большое количество стандартных классов Java НЕ ориентировано на многопотоковое исполнение.Действительно, классический случай - StringBuilder
, который является не-ориентированным на многопоточность повторным реализацией StringBuffer
.Другие являются большинством типов коллекций в java.util
!
По сути, у вас есть два варианта:
Сделать класс по своей сути поточно-ориентированным и принять, что это происходитс накладными расходами во время выполнения.
Сделайте класс по своей природе не поточно-ориентированным и убедитесь, что вы используете его только теми способами, которые решают эту проблему соответствующим образом.(Один из способов - ограничить экземпляры потоками. Другой - использовать некоторую форму внешней синхронизации.)