Безопасность потоков в классе Java

Почему этот класс Java не является поточно-безопасным.

class TestClass {  
   private int x;

   int get() {
       return x;
   }

   void set(int x) {
       this.x = x;
   }  
}

Я прочитал, что ключевое слово synchronized необходимо, чтобы сделать его потокобезопасным? В конце концов, разве операции не выполняются внутри атомарного?

16
задан Ben 1 January 2012 в 14:02
поделиться

3 ответа

Хотя само присваивание является атомарной операцией, из-за разного аппаратного обеспечения и реализации компилятора разные потоки могут видеть разные значения члена x. То есть изменение одного потока может быть невидимым для другого потока из-за какого-то кэширования. Обычно это называется проблемой видимости потока.

Вы можете правильно синхронизировать свой код, либо синхронизируя его на мониторе (используя ключевое слово synchronized или блокировки java.util.concurrent), либо объявив x volatile.

12
ответ дан 30 November 2019 в 21:18
поделиться

Поскольку поле "x" не объявлено изменчивым, JVM не требует, чтобы "x" был виден всем другим потокам. т.е. если один поток постоянно читает значение 'x', а другой поток записывает его, возможно, что читающий поток никогда не «увидит» изменение значения.

Синхронизированное ключевое слово не требуется, но будет работать, так как оно создаст необходимый барьер памяти/очистку кеша, чтобы обеспечить видимость «x», но использование ключевого слова volatile в этом случае будет более эффективным.

6
ответ дан 30 November 2019 в 21:18
поделиться

При использовании нескольких процессоров некоторые значения могут кэшироваться процессором и могут не отражать изменения, внесенные другими потоками/процессорами для тех же объектов. На самом деле, JVM может работать таким образом даже с одним процессором.

Спецификация языка явно требует, чтобы синхронизированные методы представляли барьер памяти и требовали повторного считывания всех переменных экземпляра из памяти.

Поскольку ваш код не синхронизирован, один поток может установить значение, но другой поток вернет значение, все еще кэшированное этим потоком.

Прочтите главу 'Память и блокировки' Спецификации языка Java.

9
ответ дан 30 November 2019 в 21:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: