Если несколько потоков могут получить доступ к полю, оно должно быть помечено как изменчивое?
чтение нескольких потоков (общие проблемы параллелизма, ключевое слово volatile, модель) Я смущен проблемами параллелизма в Java.
У меня есть много полей, к которым обращается более одного потока. Должен ли я пройти через них и отметить их все как изменчивые?
при создании класса я не знаю, будет ли несколько потоков обращаться к нему, поэтому, конечно, небезопасно позволять любому полю не будет изменчивый, поэтому, насколько я понимаю, есть очень мало случаев, когда вы не использовали бы его. Правильно ли это?
для меня это специфично для версии 1.5 JVMs и позже, но не ограничивайтесь ответом о моей конкретной настройке.
4 ответов
если поле доступно нескольким потокам, оно должно быть volatile
или final
, или доступ только с синхронизированными блоками. В противном случае назначенные значения могут быть недоступны для других потоков.
класс должен быть специально предназначен для одновременного доступа нескольких потоков. Просто отмечать поля испаряющие или окончательные не достаточно для поток-безопасности. Существуют проблемы согласованности (атомарность изменений в нескольких полях), проблемы с сигнализацией между потоками (например используя wait
и notify
) и т. д.
таким образом, безопаснее всего предположить, что объект должен быть видимым только для одного потока, если он не задокументирован иначе. Сделать все ваши объекты потокобезопасными не обязательно и дорого-с точки зрения скорости программного обеспечения, но что более важно, с точки зрения расходов на разработку.
вместо этого программное обеспечение должно быть разработано таким образом, чтобы параллельные потоки взаимодействовали друг с другом как можно меньше, предпочтительно вообще. Точки, где они необходимо четко определить взаимодействие, чтобы можно было разработать надлежащие элементы управления параллелизмом.
Ну, вы прочитали эти другие вопросы, и я предполагаю, что вы уже прочитали ответы, поэтому я просто выделю некоторые ключевые моменты:
- они будут меняться? если нет, вам не нужно фитонциды
- если да, то значение поля связано с другим? если да, перейдите к пункту 4
- сколько потоков будет менять? если только 1, то volatile-это все, что вам нужно
- если ответ на номер 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 не достаточно.
рассмотрим также случай, когда переменная ссылается на изменяемый объект (скажем, массив или коллекцию), то взаимодействие с этим объектом не будет потокобезопасным только потому, что ссылка является неустойчивой.