Как использовать Несколько Переменных для Объема блокировки в C#

У меня есть ситуация, где блок кода должен быть выполнен, только если два объекта блокировщика свободны.

Я надеялся, что будет что-то как:

lock(a,b)
{
    // this scope is in critical region
} 

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

lock(a)
{
    lock(b)
    {
        // this scope is in critical region
    }
}

Это будет даже работать как ожидалось? Хотя код компилирует, но я не уверен, достиг ли он того, к чему я ожидаю это.

9
задан ChrisF 20 May 2010 в 13:19
поделиться

3 ответа

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

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

Однако, если какой-то другой код уже заблокировал b , то этот код не будет делать то, что вы ожидаете. Вам также необходимо убедиться, что везде, где вам нужно заблокировать как a , так и b , вы пытаетесь установить блокировки в одном и том же порядке. Если вы сначала получите b , а затем a , вы вызовете тупик.

5
ответ дан 4 December 2019 в 07:04
поделиться

Запрос блокировки на обоих должен работать нормально. lock(a) будет блокироваться, пока a не освободится. Как только вы получите эту блокировку, lock(b) будет блокировать, пока у вас не будет b. После этого у вас будет и то, и другое.

Одна вещь, с которой нужно быть очень осторожным, - это порядок. Если вы собираетесь сделать это, убедитесь, что вы всегда получаете блокировку на a перед получением блокировки на b. В противном случае вы легко можете оказаться в тупиковой ситуации.

11
ответ дан 4 December 2019 в 07:04
поделиться
lock(a) lock(b) { // this scope is in critical region }

Это может привести к блокировке, пока поток не получит блокировку для a . Затем, после получения этой блокировки, он будет блокироваться до тех пор, пока поток не сможет получить блокировку для b . Итак, это работает, как ожидалось.

Однако вы должны быть осторожны, чтобы не сделать этого где-то еще:

lock(b) lock(a) { // this scope is in critical region }

Это может привести к ситуации взаимоблокировки, в которой поток 1 получил блокировку для a и ожидает получения блокировки. для b , а поток 2 получил блокировку для b и ожидает получения блокировки для a .

16
ответ дан 4 December 2019 в 07:04
поделиться
Другие вопросы по тегам:

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