Параллелизм: Condition.awaitNanos () не снимает блокировку - PullRequest
3 голосов
/ 07 марта 2012

В моей программе я использую объект Condition, созданный из

private static final Lock lock = new ReentrantLock();

примерно так:

private static final Condition operationFinished = MyClass.lock.newCondition();

Иногда (как это всегда происходит с проблемами параллелизма) я сталкиваюсь со следующимиповедение:

  1. Thread1 получает блокировку
  2. Thread1 вызывает operationFinished.awaitNanos() - это должно приостановить Thread1 и снять блокировку.
  3. Thread2 пытается получить такую ​​же блокировку,но отладочный вывод показывает, что Thread1 все еще удерживает блокировку!

Согласно документации это поведение невозможно, поскольку при awaitNanos() Thread1 сначала снимает блокировку, а затем приостанавливает работу.Если он не снимает блокировку, он не приостанавливается, поэтому Thread2 никогда не сможет даже попытаться захватить блокировку.

Кто-нибудь испытывал нечто подобное?Эта ошибка случается один раз в 100 раз - но все же это указывает на то, что я либо не использую утилиты параллелизма надлежащим образом, либо что в пакете java.utils.concurrent. * Есть какая-то ошибка (в чем я сомневаюсь).

ОБНОВЛЕНИЕ:

В ответ на ответ Петерса:

Я наблюдаю следующее поведение: Очевидно, 2 потока взаимоблокируют друг друга.Я вижу, что блоки Thread2 (ожидающие блокировки) и в то же время awaitNanos() в Thread1 никогда не прерываются.

Ответы [ 2 ]

1 голос
/ 07 марта 2012

Вы уверены, что время ожидания еще не закончено?Если вы будете ждать в течение короткого периода времени (например, несколько сотен наносекунд), время ожидания может истечь, прежде чем Thread2 сможет полностью запуститься, и в этом случае Thread1 может быть сначала активирован.

1 голос
/ 07 марта 2012

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

Скажем, у вас есть thread1, который удерживает блокировку, но в awaitNanos () у вас есть Thread2, который пытается получить блокировку (), но иногда Thread3 также удерживает блокировку ....

Я бы сделал jstack -l {pid}, чтобы проверить все потоки, которые могут удерживать блокировку.

Если блокировка заблокирована, awaitLock (и wait ()) не вернутся, так как перед этим должны получить блокировку. (Если оно не прервано)

...