У меня есть ситуация, где блок кода должен быть выполнен, только если два объекта блокировщика свободны.
Я надеялся, что будет что-то как:
lock(a,b)
{
// this scope is in critical region
}
Однако, кажется, нет ничего как этот. Делает это означает единственный путь к тому, чтобы сделать, это:
lock(a)
{
lock(b)
{
// this scope is in critical region
}
}
Это будет даже работать как ожидалось? Хотя код компилирует, но я не уверен, достиг ли он того, к чему я ожидаю это.
Я ожидал, что это произойдет, хотя есть случай, когда это потенциально может вызвать состояние взаимоблокировки.
Обычно код пытается заблокировать a
, а затем переходит к блокировке b
, если это удается. Это означает, что код будет выполнен только в том случае, если он сможет заблокировать как a
, так и b
. Это то, что вам нужно.
Однако, если какой-то другой код уже заблокировал b
, то этот код не будет делать то, что вы ожидаете. Вам также необходимо убедиться, что везде, где вам нужно заблокировать как a
, так и b
, вы пытаетесь установить блокировки в одном и том же порядке. Если вы сначала получите b
, а затем a
, вы вызовете тупик.
Запрос блокировки на обоих должен работать нормально. lock(a)
будет блокироваться, пока a
не освободится. Как только вы получите эту блокировку, lock(b)
будет блокировать, пока у вас не будет b
. После этого у вас будет и то, и другое.
Одна вещь, с которой нужно быть очень осторожным, - это порядок. Если вы собираетесь сделать это, убедитесь, что вы всегда получаете блокировку на a
перед получением блокировки на b
. В противном случае вы легко можете оказаться в тупиковой ситуации.
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
.