Как использовать несколько переменных для блокировки Scope в C # - PullRequest
9 голосов
/ 20 мая 2010

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

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

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

Однако, похоже, ничего подобного нет. Значит ли это, что единственный способ сделать это:

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

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

Ответы [ 3 ]

16 голосов
/ 20 мая 2010
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.

11 голосов
/ 20 мая 2010

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

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

5 голосов
/ 20 мая 2010

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

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

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

...