【问题标题】:how to prevent a deadlock when you need to lock multiple objects当您需要锁定多个对象时如何防止死锁
【发布时间】:2013-05-21 07:57:52
【问题描述】:

将此代码映像:

你有 2 个数组,你需要同时锁定它们(出于任何原因 - 你只需要保持锁定它们,因为它们以某种方式相互依赖) - 你可以嵌套锁

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

但这可能会导致死锁,以防你代码的其他部分的人会这样做

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

数组 1 被锁定 - 执行上下文切换 - 然后数组 2 被第二个线程锁定。

有没有办法自动锁定它们?比如

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

我知道我可以只创建一些额外的“锁定对象”并锁定它,而不是在我的代码中到处都是两个数组,但这对我来说似乎不正确......

【问题讨论】:

  • 创建一个额外的锁对象正确的。
  • 使用将锁定两个项目的单个锁定对象是要走的路。

标签: c#


【解决方案1】:

一般来说,您应该避免锁定可公开访问的成员(在您的情况下是数组)。你宁愿有一个private static object 你会锁定。

【讨论】:

  • 您能详细说明一下吗?我不明白你的意思。如果这是需要公开的东西怎么办,比如一些全局数组
  • 数组可以公开,这不是问题。您应该锁定的内容不应该公开。所以在你的类中定义一个private static object syncRoot = new object(); 然后锁定它:lock(syncRoot) { ... do something with the array ... }
  • 好的 - 但是如果我从其他无法访问 syncRoot 的对象访问这个公共数组怎么办 - 我将如何锁定它?在读取数组时如何防止数组被修改?
  • @Petr 可以改为列表,并在适当的地方重载 add/remove/clear 等方法,并在调用 base 方法时锁定在重载中(顺便说一下,有各种同步.net 中的集合,System.Collections.Concurrent)
  • 除非数组也是静态的,否则不要将锁定对象设为静态 - 否则您将毫无意义地阻止同时访问完全独立的数组。无意义的锁定是不好的。如果数组不是静态的,则将锁定对象设为非静态字段。 (我假设这两个数组当然都在同一个类中。)
【解决方案2】:

您不应该像 Darin 所说的那样允许锁定可公开访问的变量。例如

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

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

宁愿做这样的事情。

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);
        }
    }
}

这样做的原因是,如果您有多个线程访问多个公共同步结构,那么就会运行非常真实的死锁可能性。然后你必须非常小心你的编码方式。如果您将您的图书馆提供给其他人使用,您可以确定您可以抓住锁吗?也许有人使用你的图书馆也抓住了锁,你们两个之间已经陷入僵局。这就是微软不推荐使用 SyncRoot 的原因。

【讨论】:

    【解决方案3】:

    我不确定您所说的锁定数组是什么意思。 您可以轻松地在单个锁中对两个数组执行操作。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多