Нужно ли синхронизировать доступ / запись в логический объект? - PullRequest
6 голосов
/ 16 апреля 2010

Это может показаться очень глупым вопросом. Учтите это:

У меня есть простой логический объект с геттером и сеттером. Теперь оба метода вызываются из множества потоков очень часто.

  1. Нужна ли синхронизация для этого логического значения?
  2. Также являются ли логические назначения атомарными операциями?

[UPDATE]: Я уже знаю об атомном логическом. У меня уже есть много разных решений, но я специально искал ответы и обоснование ответов на 2 вопроса.

Ответы [ 7 ]

10 голосов
/ 16 апреля 2010

Нет, логический доступ НЕ является атомарным (на уровне машинного кода), хотя он требует "только 1 операции в Java".

Поэтому да, вам нужна синхронизация для логического значения.

См. Слайды 4-6 из этой презентации с примерами кода.

В связанной заметке, вы не должны синхронизироваться с логическим значением

3 голосов
/ 16 апреля 2010
  1. С технической точки зрения синхронизация не требуется, чтобы записи в одном потоке воспринимались в другом потоке. То, что вам нужно, это случается до края. Вполне вероятно, что либо volatile, либо synchronized будет использоваться для достижения преимущества до того Оба эти метода приводят к синхронизации с краем. Поэтому на практике вы, вероятно, будете использовать синхронизацию для управления состоянием вашего логического значения.
  2. Да. Обратите внимание, что вы не меняете состояние объекта Boolean. Вы только изменяете ссылку на логический объект. В разделе 17.7 спецификации языка говорится, что «запись и чтение ссылок всегда атомарны».

Обновление: позвольте мне разъяснить необходимость преграды, предшествующей событию. Без края, предшествующего событию, не гарантируется, что изменения, сделанные одним потоком в переменной, когда-либо будут восприняты другими потоками. Это не просто, что изменение может быть воспринято в неподходящее время, например, между чтением и записью. Изменение может никогда не восприниматься.

Допустим, у нас есть логическая переменная, которую мы инициализируем как false. Тогда мы начинаем две темы. Первый поток устанавливает переменную в true и останавливается. Второй поток постоянно проверяет переменную, пока она не станет истинной, после чего она останавливается. Нет гарантии, что второй поток когда-либо увидит переменную как true.

3 голосов
/ 16 апреля 2010
  1. Да. Но если это флаг, который записывается только из одного потока, и вы хотите обеспечить видимость для всех потоков, тогда дешевой альтернативой будет использование volatile.

  2. Да - даже несмотря на то, что внутреннее представление объекта (т. Е. Фактический флаг boolean внутри оболочки Boolean) было 64-битным, и, следовательно, он мог «разделиться» в параллельной ситуации, логическое значение может есть только одно из двух значений, верно? Так что простые присваивания (get или set) являются атомарными, но если вы делаете что-то еще (например, check-then-act), например x = !x, то это, конечно, не атомарный, если не синхронизирован.

2 голосов
/ 16 апреля 2010

Использование AtomicBoolean .

1 голос
/ 21 марта 2014

http://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html говорит, что чтение и запись примитивных переменных является атомарным.

Следовательно, возможно обеспечить строгое чередование или произойти после отношений, используя логическое значение (или изменяемое логическое значение в случае эффектов кэширования)

1 голос
/ 16 апреля 2010
  1. Нет, нет. Но объявите переменную volatile, чтобы значения отражались во всех потоках, которые обращаются к логическому значению. Если вы посмотрите на метод AtomicBoolean set(..), он также не синхронизируется.

  2. Да, практически назначение является атомным. Просто установка значения не требует синхронизации. Однако, если вы хотите сделать что-то вроде:

    if (!bool) {
       bool = false;
    }
    

    тогда вам нужна синхронизация (или AtomicBoolean, которая более эффективна, чем синхронизация)

0 голосов
/ 16 апреля 2010

, даже если он был атомарным, все еще есть вопросы синхронизации, так как вы, возможно, когда-нибудь проверите значение например if (boolVar == true) -> другой поток получает контроль do_something ();

...