2012-03-07 2 views
3

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

private static final Lock lock = new ReentrantLock(); 

как так:

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

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

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

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

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

UPDATE:

В ответ на Peters ответ:

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

ответ

1

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

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

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

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

+0

Thx для вашего ответа! Обновлен мой ответ с дополнительной информацией: блокировка определенно по-прежнему поддерживается Thread1, так как я вижу блокировку Thread2 на 'lock()'. – quaylar

+0

И Thread1 окончательно находится в ожиданииNanos()? Можете ли вы показать нам трассировку стека для этих двух потоков и любого другого потока, который может удерживать блокировку. например из 'jstack' –

+0

Я понял, что возможно, что Thread2 попытается захватить блокировку, когда Thread1 все еще не ждетNanos().Но даже в этом случае Thread2 блокируется до тех пор, пока Thread1 не вызовет waitNanos(), а затем захватит блокировку ... – quaylar

1

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

+0

Я выбрасываю исключение, если время ожидания истекает, но не возникает никакого исключения, когда эта проблема возникает, и больше нет отладочного вывода (который должен быть выведен в случае, если Thread1 продолжается после ожидания()). – quaylar

+0

Вы освобождаете блокировку перед выбросом исключения? И помните, что если поток, бросающий исключение, не является основным потоком, тогда он может вызвать вызов стек в этом потоке, а затем исчезнуть, если вы не установили обработчик исключенных исключений для потока. –

+0

Дело в том, что в текущем случае исключение никогда не выбрасывается, поэтому awaitNanos() никогда не возвращается ... кажется Thread1 и Thread2 блокируют друг друга. – quaylar

Смежные вопросы