Eclipse является симпатичным чрезмерно увеличенным в размерах IDE. Можно минимизировать его путем превращения автоматического здания проекта в соответствии с Проектом-> Сборка Автоматически. Этому также можно помочь путем закрытия любого открытого проекта, Вы в настоящее время не продолжаете работать.
if (foo.needsProcessing()) {
synchronized (foo) {
foo.process(); // foo's state may be changed here
}
}
Я думаю, что в приведенном выше фрагменте есть состояние гонки, которое может привести к тому, что foo.process ()
иногда вызывается дважды на тот же объект. Так должно быть:
synchronized (foo) {
if (foo.needsProcessing()) {
foo.process(); // foo's state may be changed here
}
}
Неужели синхронизация на локальных источниках настолько плоха?
Неплохо синхронизировать локальные источники как таковые . Реальные проблемы заключаются в следующем:
синхронизируются ли разные потоки на правильных объектах для достижения надлежащей синхронизации, и
может ли что-то еще вызвать проблемы при синхронизации на этих объектах.
IDE должна помочь вам, если она делает ошибку, вы не должны » наклониться и доставить удовольствие.
Вы можете отключить эту проверку в IntelliJ. (Забавно, что это единственный параметр, который включен по умолчанию в разделе «Проблемы с потоками». Это самая распространенная ошибка, которую делают люди?)
Рефакторинг тела цикла в отдельный метод, принимающий foo
в качестве параметра.
Нет идеального автоинтеллекта. Я думаю, что ваша идея синхронизации по локальной переменной вполне верна. Так что, возможно, сделайте это по-своему (что правильно) и предложите JetBrains настроить проверку.
В мире .NET объекты иногда несут свой объект блокировки как свойство.
synchronized (foo.getSyncRoot()) {
if (foo.needsProcessing()) {
foo.process(); // foo's state may be changed here
}
}
Это позволяет объекту выдавать другой объект блокировки, в зависимости от его реализации (например, делегирование монитора объекту базовое соединение с базой данных или что-то в этом роде).
Нет ничего плохого в вашей синхронизации с объектом в коллекции. Вы можете попробовать заменить foreach обычным циклом for:
for (int n = 0; n < Foos.length; n++) {
Foo foo = Foos[n];
if (null != foo && foo.needsProcessing()) {
synchronized (foo) {
foo.process(); // foo's state may be changed here
}
}
}
или даже (чтобы детектор не обнаружил Foo foo
):
for (int n = 0; n < foos.length; n++) {
if (null != foos[n] && foos[n].needsProcessing()) {
synchronized (foos[n]) {
foos[n].process(); // foos[n]'s state may be changed here
}
}
}
Не использовать временное значение для предотвращения множественного foos [n]
- не лучшая практика, но если она работает для предотвращения нежелательного предупреждения, вы можете жить с этим. Добавьте комментарий, почему этот код имеет отклоняющуюся форму. : -)