简体   繁体   English

如何在需要锁定多个对象时防止死锁

[英]how to prevent a deadlock when you need to lock multiple objects

Image this code: 想象这段代码:

You have 2 arrays, and you need to lock both of them in same moment (for any reason - you just need to keep locked both of them because they are somehow depending on each other) - you could nest the lock 你有2个阵列,你需要在同一时刻锁定它们(出于任何原因 - 你只需要保持锁定它们两个因为它们以某种方式相互依赖) - 你可以嵌套锁

lock (array1)
{
    lock (array2)
    {
        ... do your code
    }
}

but this may result in a deadlock in case that someone in other part of your code would do 但是,如果代码的其他部分中有人会这样做,这可能会导致死锁

lock (array2)
{
    lock (array1)
    {
        ... do your code
    }
}

and array 1 was locked - execution context switched - then array 2 was locked by second thread. 并且数组1被锁定 - 执行上下文切换 - 然后数组2被第二个线程锁定。

Is there a way to atomically lock them? 有没有办法以原子方式锁定它们? such as

lock_array(array1, array2)
{
    ....
}

I know I could just create some extra "lock object" and lock that instead of both arrays everywhere in my code, but that just doesn't seem correct to me... 我知道我可以创建一些额外的“锁定对象”并在我的代码中锁定而不是两个数组,但这对我来说似乎不正确...

In general you should avoid locking on publicly accessible members (the arrays in your case). 通常,您应该避免锁定可公开访问的成员(在您的情况下为数组)。 You'd rather have a private static object you'd lock on. 你宁可拥有一个你要锁定的private static object

You should never allow locking on publicly accessible variable as Darin said. Darin说,你永远不应该允许锁定可公开访问的变量。 For example 例如

public class Foo
{
    public object Locker = new object();
}

public class Bar
{
    public void DoStuff()
    {
        var foo = new Foo();
        lock(foo.Locker)
        {
            // doing something here
        }
    }
}

rather do something like this. 而是做这样的事情。

public class Foo
{
    private List<int> toBeProtected = new List<int>();
    private object locker = new object();

    public void Add(int value)
    {
        lock(locker)
        {
            toBeProtected.Add(value);
        }
    }
}

The reason for this is if you have multiple threads accessing multiple public synchronization constructs then run the very real possiblity of deadlock. 原因是如果您有多个线程访问多个公共同步构造,那么就可以运行非常真实的死锁。 Then you have to be very careful about how you code. 然后你必须非常小心你的编码方式。 If you are making your library available to others can you be sure that you can grab the lock? 如果您正在向其他人提供您的图书馆,您可以确定您可以获得锁定吗? Perhaps someone using your library has also grabbed the lock and between the two of you have worked your way into a deadlock scenario. 也许有人使用你的库也抓住了锁,你们两个之间已经陷入了死锁的境地。 This is the reason Microsoft recommend not using SyncRoot. 这是Microsoft建议不使用SyncRoot的原因。

I am not sure what you mean by lock to arrays. 我不确定锁定数组是什么意思。 You can easily perform operation on both arrays in single lock. 您可以在单个锁中轻松地对两个阵列执行操作。

static readonly object a = new object();
lock(a){
    //Perform operation on both arrays
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM