9

我有一种情况,只有当两个储物柜对象空闲时才应该执行一段代码。

我希望会有类似的东西:

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

然而,似乎没有这样的事情。那么这是否意味着这样做的唯一方法是:

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

这甚至会按预期工作吗?虽然代码可以编译,但我不确定它是否能达到我的预期。

4

3 回答 3

16
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

于 2010-05-20T13:22:15.307 回答
11

请求锁定两者应该可以正常工作。 lock(a)将阻塞直到a空闲。一旦你拥有了那个锁,lock(b)就会阻塞直到你拥有b. 之后,你拥有两者。

您需要非常小心的一件事是订单。如果您要这样做,请确保您始终在上锁a之前先上锁b。否则你很容易发现自己陷入僵局。

于 2010-05-20T13:20:44.910 回答
5

我希望它会发生,尽管在某些情况下它可能会导致死锁情况。

通常,代码将尝试锁定,然后如果成功a则继续锁定。这意味着它只有在同时锁定和b时才会执行代码。这就是你想要的。ab

但是,如果其他一些代码已经被锁定,b那么这个代码将不会像你期望的那样做。您还需要确保在需要锁定两者的任何地方都a尝试b以相同的顺序获得锁定。如果你b先得到然后a你会导致死锁。

于 2010-05-20T13:21:36.920 回答