Если несколько потоков могут получить доступ к полю, оно должно быть помечено как изменчивое?

чтение нескольких потоков (общие проблемы параллелизма, ключевое слово volatile, модель) Я смущен проблемами параллелизма в Java.

У меня есть много полей, к которым обращается более одного потока. Должен ли я пройти через них и отметить их все как изменчивые?

при создании класса я не знаю, будет ли несколько потоков обращаться к нему, поэтому, конечно, небезопасно позволять любому полю не будет изменчивый, поэтому, насколько я понимаю, есть очень мало случаев, когда вы не использовали бы его. Правильно ли это?

для меня это специфично для версии 1.5 JVMs и позже, но не ограничивайтесь ответом о моей конкретной настройке.

4 ответов


если поле доступно нескольким потокам, оно должно быть volatile или final, или доступ только с синхронизированными блоками. В противном случае назначенные значения могут быть недоступны для других потоков.

класс должен быть специально предназначен для одновременного доступа нескольких потоков. Просто отмечать поля испаряющие или окончательные не достаточно для поток-безопасности. Существуют проблемы согласованности (атомарность изменений в нескольких полях), проблемы с сигнализацией между потоками (например используя wait и notify) и т. д.

таким образом, безопаснее всего предположить, что объект должен быть видимым только для одного потока, если он не задокументирован иначе. Сделать все ваши объекты потокобезопасными не обязательно и дорого-с точки зрения скорости программного обеспечения, но что более важно, с точки зрения расходов на разработку.

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


Ну, вы прочитали эти другие вопросы, и я предполагаю, что вы уже прочитали ответы, поэтому я просто выделю некоторые ключевые моменты:

  1. они будут меняться? если нет, вам не нужно фитонциды
  2. если да, то значение поля связано с другим? если да, перейдите к пункту 4
  3. сколько потоков будет менять? если только 1, то volatile-это все, что вам нужно
  4. если ответ на номер 2 " нет " или более одного потока собирается написать для него, то Летучий в одиночку не хватает, вам, вероятно, потребуется синхронизировать доступ

добавлено:
Если поле ссылается на объект, то оно будет иметь собственные поля, и все эти соображения также применимы к этим полям.


Если вам нужно спросить, используйте замки. volatile может быть полезно в некоторых случаях, но это очень трудно сделать правильно. Например:

class Foo {
  private volatile int counter = 0;
  int Increment() {
    counter++;
    return counter;
  }
}

если два потока работают Increment() в то же время, возможно, в результате будет counter = 1. Это потому, что компьютер сначала получит counter, добавьте один, а затем сохраните его обратно. Volatile просто заставляет сохранять и загружать данные в определенном порядке относительно других операторов.

отметим, что synchronized обычно устраняет потребность в volatile - если все обращения к данному полю защищены одним и тем же монитором, volatile никогда не понадобятся.

используя volatile сделать алгоритмы без блокировки очень и очень сложно; придерживайтесь synchronized если у вас нет твердых доказательств того, что он уже слишком медленный, и вы провели подробный анализ алгоритма, который планируете реализовать.


короткий ответ: нет. Решение проблем с потоками требует больше размышлений и планирования, чем это. См.этой для некоторых ограничений, когда volatile помогает для резьбы, а когда нет. Изменение значений должно быть правильно синхронизировано, но, как правило, изменение требует состояния более одной переменной за раз. Скажем, например, у вас есть переменная и вы хотите изменить ее, если она отвечает критериям. Чтение из массива и запись в массив различные инструкции, и должны быть синхронизированы вместе. Volatile не достаточно.

рассмотрим также случай, когда переменная ссылается на изменяемый объект (скажем, массив или коллекцию), то взаимодействие с этим объектом не будет потокобезопасным только потому, что ссылка является неустойчивой.