Безопасен ли класс с синхронизированной записью в логическую переменную экземпляра? Например.:
boolean foo = true;
public synchronized void setFoo(boolean foo) {
this.foo = foo;
}
public boolean getFoo() {
return foo;
}
Да, на самом деле я просто рассматривал реализацию AtomicBoolean, чтобы посмотреть, смогу ли я получить ответ таким образом. Похоже, что геттер/сеттер не имеет механизма блокировки. Просто значение нестабильно. Я спрашиваю об этом конкретном сценарии, потому что мне нужно изменить некоторый существующий код в классе, который уже в значительной степени синхронизирован, и мне было интересно, можно ли просто удалить синхронизацию из метода получения.
В принципе, нет, это не работает. Если вас не волнует чтение памяти, то синхронизация, которую вы используете, ничего не дает. А если вас это волнует, то вам необходимо синхронизировать и то, и другое. Компилятор должен знать, что он не может оптимизировать чтение в регистр или что-то подобное, значение необходимо перечитать.




Нет, не потокобезопасный.
Вы не учли проблему наглядности.
Изменения примитива boolean не обязательно видны во всех потоках. Из-за особенностей работы современных процессоров, оптимизации, выполненной JIT компилятором и Моделью памяти Java, один поток может не видеть изменения, внесенные другим потоком.
volatileОдин из способов решения проблемы видимости — пометить примитивную переменную boolean как volatile.
AtomicBooleanДругой способ — заменить объект AtomicBoolean вместо примитива boolean. Отметьте переменную AtomicBoolean как final, чтобы предотвратить случайное присвоение другого экземпляра.
final AtomicBoolean atomicFoo = new AtomicBoolean ( true ) ;
Затем используйте методы получения/установки для доступа к логическим полезным данным, хранящимся в этом объекте, и манипулирования ими в потокобезопасном режиме.
Лично я предпочитаю занятия Atomic…. Использование этих классов означает, что программист должен вызывать методы, а не просто выполнять назначения. Это явление является постоянным напоминанием программисту о том, что он работает в многопоточной ситуации.
Что касается существующего кода, то компилятор окажет огромную помощь при рефакторинге для использования AtomicBoolean. Каждое место, где был осуществлен доступ или манипулирование примитивом, будет выделено как ошибка компилятора, требующая вашего внимания.
Рассматривали ли вы AtomicBoolean, чтобы развеять все сомнения?