Синхронизация на локальных переменных

Eclipse является симпатичным чрезмерно увеличенным в размерах IDE. Можно минимизировать его путем превращения автоматического здания проекта в соответствии с Проектом-> Сборка Автоматически. Этому также можно помочь путем закрытия любого открытого проекта, Вы в настоящее время не продолжаете работать.

28
задан Sergey Mikhanov 27 November 2009 в 14:10
поделиться

6 ответов

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
    }
}

Неужели синхронизация на локальных источниках настолько плоха?

Неплохо синхронизировать локальные источники как таковые . Реальные проблемы заключаются в следующем:

  • синхронизируются ли разные потоки на правильных объектах для достижения надлежащей синхронизации, и

  • может ли что-то еще вызвать проблемы при синхронизации на этих объектах.

22
ответ дан 28 November 2019 в 03:44
поделиться

IDE должна помочь вам, если она делает ошибку, вы не должны » наклониться и доставить удовольствие.

Вы можете отключить эту проверку в IntelliJ. (Забавно, что это единственный параметр, который включен по умолчанию в разделе «Проблемы с потоками». Это самая распространенная ошибка, которую делают люди?)

2
ответ дан 28 November 2019 в 03:44
поделиться

Рефакторинг тела цикла в отдельный метод, принимающий foo в качестве параметра.

1
ответ дан 28 November 2019 в 03:44
поделиться

Нет идеального автоинтеллекта. Я думаю, что ваша идея синхронизации по локальной переменной вполне верна. Так что, возможно, сделайте это по-своему (что правильно) и предложите JetBrains настроить проверку.

1
ответ дан 28 November 2019 в 03:44
поделиться

В мире .NET объекты иногда несут свой объект блокировки как свойство.

synchronized (foo.getSyncRoot()) {
    if (foo.needsProcessing()) {
        foo.process();  // foo's state may be changed here
    }
}

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

0
ответ дан 28 November 2019 в 03:44
поделиться

Нет ничего плохого в вашей синхронизации с объектом в коллекции. Вы можете попробовать заменить 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] - не лучшая практика, но если она работает для предотвращения нежелательного предупреждения, вы можете жить с этим. Добавьте комментарий, почему этот код имеет отклоняющуюся форму. : -)

0
ответ дан 28 November 2019 в 03:44
поделиться
Другие вопросы по тегам:

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