Как удалить тупик в коде Java с помощью NetBeans - PullRequest
3 голосов
/ 20 октября 2010

У меня есть старый код в Java, который блокируется ... Я никогда не использовал netbeans в качестве инструмента разработки ... однако мне нужно исправить код.

Я запустил приложение в режиме отладки, нажал на проверку на взаимоблокировку и NetBeans вывел экран. Два из четырех потоков были в красном ... см. Скриншот ниже.

Я новичок в многопоточности, и к тому же этот код не мой ...

Что, скорее всего, является причиной проблемы?

alt text

1 Ответ

5 голосов
/ 20 октября 2010

Насколько я могу судить, проблема, скорее всего, связана с тем, каким образом (или, точнее, порядок, в котором) несколько потоков получают и снимают блокировки. В приведенном выше примере двум потокам необходим доступ к двум блокировкам (или мониторам):

  • nano.toolbox.strategies.ESMarketMaker
  • nano.toolbox.strategies.ExecutionManager

Из трассировки стека в двух потоках, которые в настоящее время находятся в тупике, мы можем видеть, что поток 'ExecutionManager' получил монитор ExecutionManager, но ожидает получения (все еще удерживая монитор 'ExecutionManager') монитора 'ESMarketMaker'.

Поток StrategyManager, с другой стороны, приобрел монитор ESMarketMaker, но ожидает (пока все еще держит монитор ESMarketMaker) монитора ExecutionManager.

Это классовый пример взаимоблокировок и множества способов, которыми порядок получения блокировок может вызвать взаимоблокировки.

Существует множество способов решения подобных проблем:

  • Если возможно, все потоки, нуждающиеся в некотором наборе блокировок для работы, должны получить общие блокировки в том же порядке (обратный порядок - проблема в вышеупомянутой взаимоблокировке). Но это не всегда возможно, так как несколько потоков могут использовать только частично перекрывающиеся блокировки в разных условиях, поэтому может быть сложно или невозможно разработать протокол сбора данных, который обеспечит равномерное упорядочение.
  • Вместо этого вы также можете использовать tryLock (), который является неблокирующим захватом, он возвращает флаг, указывающий на успех или неудачу, и дает вам возможность сделать что-то еще перед повторной попыткой. В этом случае я бы порекомендовал, чтобы в случае сбоя сбора данных он отбрасывал все имеющиеся в настоящее время блокировки и пытался снова с нуля (таким образом, уступая место любому, кто заблокирован на любой или всех блокировках, удерживаемых текущим потоком, завершить работать, возможно, освобождая блокировки, необходимые этой нити при повторной попытке).

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

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

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

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