Не могли бы вы объяснить порядок блокировки? - PullRequest
25 голосов
/ 23 декабря 2009

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

A.lock();
B.lock();
B.unlock();
A.unlock();

Но что произойдет, если я сделаю так:

A.lock();
B.lock();
A.unlock();
B.unlock();

Я пытаюсь сделать сценарий тупика, но если я всегда блокирую A раньше, чем B, то я не знаю, как возникнет тупик. Ты мне поможешь?

Ответы [ 7 ]

40 голосов
/ 21 января 2012

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

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

Рассмотрим:

A.lock();
B.lock();
Foo();
A.unlock();
Bar();
B.unlock();

Если Bar() попытается вернуть А, вы фактически нарушили порядок блокировки. Вы держите B, а затем пытаетесь получить A. Теперь он может тупик.

Если вы разблокируете в стиле обратного порядка (что очень естественно, если вы используете RAII):

A.lock();
B.lock();
Foo();
B.unlock();
Bar();
A.unlock();

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

21 голосов
/ 23 декабря 2009

Порядок блокировки только означает, что вы предотвращаете взаимные блокировки, получая блокировки в фиксированном порядке, и не получаете блокировки снова после начала разблокировки.

Я не думаю, что порядок разблокировки здесь имеет какое-либо значение (на самом деле, было бы полезно снять блокировку как можно скорее, даже если она вышла из строя)

9 голосов
/ 23 декабря 2009

Ваш пример никогда не заходит в тупик с самим собой. Разблокировка в обратном порядке не важна, она в последовательном порядке. Это заблокирует блокировку, даже если разблокировка производится в обратном порядке

Thread 1

A.lock();
B.lock();
B.unlock();
A.unlock();

Thread 2

B.lock();
A.lock();
A.unlock();
B.unlock();
2 голосов
/ 23 декабря 2009

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

Дополнительная литература

1 голос
/ 23 декабря 2009

Порядок разблокировки не влияет на склонность вашей системы к взаимоблокировке, однако есть одна причина подумать о порядке разблокировки:

Чтобы избежать взаимных блокировок, вы должны убедиться, что ваши блокировки / разблокировки сопряжены, чтобы вы никогда не пропустили разблокировку. В качестве стилистического подхода, заметно выделяя блоки кода, отвечающие за конкретную блокировку, гораздо проще визуально определить, что блокировки и разблокировки являются парными. Конечным результатом является то, что явно правильный код, вероятно, примет и освободит блокировки, как вы описали.

0 голосов
/ 18 сентября 2017
      > lock(B)                                                                                                                                                                                                 
      >  ----------    lock(C)
      >  ----------    lock(B)    >>>> would block here 
      >  ----------    release(B)
      >  ----------    release(C)
      > lock(C)       >>>>>> would block here 
      > release(B)
      > release(C)

Их ответ отличный, вот еще одна ситуация, в которой может возникнуть тупик, если неупорядоченная блокировка и разблокировка выполняются. Одним словом, Неупорядоченный выпуск и блокировка нарушают предположение, которое мы использовали для разработки нашего общего управления ресурсами и критической зоны.

0 голосов
/ 10 июля 2012

А для Java разблокировка происходит в обратном порядке, если synchronized Ключевое слово используется для блокировки. Нет возможности разблокировать в другом порядке для использования ключевого слова synchronized.

synchronized(a) {
  synchronized(b) {
    // statements
  }
}
...