【问题标题】:What exactly means locking on an object?锁定对象到底是什么意思?
【发布时间】:2010-01-01 09:00:18
【问题描述】:

尽管我在我的应用程序中使用了锁,但我不明白对特定引用类型进行锁定究竟是什么。我认为它只是停止线程,直到 {} 的内容完成。但是我已经读过锁定(this)是不好的,如果它是公开的 - 为什么?文章解释了它,但我不明白我不知道对象本身被锁定发生了什么。 例如,如果我使用 lock(this) 并从另一个线程调用它的方法怎么办?我以为只有锁下的代码受到保护,否则我将根本无法访问锁定的对象? 谢谢

【问题讨论】:

    标签: c# multithreading locking


    【解决方案1】:

    托管堆上的每个对象都可以用作锁定对象,这是一种在线程之间同步访问的方法。

    我认为它只是停止线程,直到 {} 的内容完成。

    好吧,lock 它会阻止 其他 线程获取锁,直到锁被释放,这最常见于 lock 语句的末尾(但它也可以是Monitor.Wait)。

    lock(this) 的用法很危险,因为锁定很复杂,准确了解哪些线程在何时锁定哪些对象对于避免死锁非常重要;但是,如果您 lock(this) 您无法控制其他线程 - 可能会(意外地)锁定同一个对象。使用private 字段进行锁定要安全得多。

    例如,如果您有(在同步列表中):

    private IList<T> innerList = ...
    public int Count { get { lock(this) { return innerList.Count; } } }
    

    那么不难想象另一段代码引用了这个同步列表,并锁定它,例如:

    SyncList<T> list = ...
    lock(list) { // lock for atomicity
        if(!list.Contains(value)) list.Add(value);
    }
    

    这是一个潜在的死锁;如果Count 没有 lock(this) 会更好,但是锁定了一个私有对象,即

    private readonly object syncLock = new object();
    public int Count { get { lock(syncLock) { return innerList.Count; } } }
    

    现在没有这个问题的风险。这里的另一个问题是类似字段的事件和[MethodImpl] 都会导致lock(this)。由于完全相同的原因,锁定 Type(对于静态方法)同样危险。

    【讨论】:

      【解决方案2】:

      对象本身未锁定。将每个对象视为具有关联锁(或监视器)。当一个线程获得锁时,如果没有第一个线程释放它,其他线程就无法获得它,要么通过调用Monitor.Exit(这是在lock 语句的末尾发生的情况),要么通过调用Monitor.Wait。调用Monitor.Enter 获取锁的线程将阻塞,直到它可以获取锁。

      对象本身根本没有“受保护” - 锁基本上是建议性的。

      不锁定“this”的原因是你不知道还有哪些代码引用了“this”。获得正确的锁定要求您知道在哪些情况下线程将拥有或不拥有锁定 - 而且您无法知道您无法控制的代码是否可以取出锁定。例外情况是,如果您为了共享锁的明确目的而公开引用(例如 .NET 1.1 集合上的 SyncRoot 属性)。

      【讨论】:

        【解决方案3】:

        锁定一个对象对对象本身没有任何作用——它只是意味着任何其他试图锁定同一个对象的线程都将被停止,直到锁定线程释放它。 lock(this) 不受欢迎的原因是对象之外的其他代码也可以锁定该对象,从而干扰其正常运行。

        【讨论】:

          【解决方案4】:

          当您使用lock(someObject) { ...code... } 时,这意味着只有当线程一次可以在锁定区域内时(假设您总是锁定同一个对象!)。尝试进入该区域的第二个线程将阻塞并且必须等到第一个线程离开。如果您有两个lock (someObject) { } 区域锁定在同一个对象上,则只有一个线程可以进入这些区域中的任何一个。

          锁定通常是一个需要保密的实现细节。锁定公共成员是一个坏主意,因为这意味着您的类的客户端也可以锁定同一个对象,这可能会导致死锁或不必要的减速。出于同样的原因,锁定this 是不好的。

          创建一个私有的新对象并锁定它。

          【讨论】:

            【解决方案5】:
            using System;
                    using System.Threading;
                    class sycexp
                            {
                            public static void Main()
                                    {
                                    exp e=new exp();
                                    Thread t1=new Thread(new ThreadStart(e.show));
                                    Thread t2=new Thread(new ThreadStart(e.show));
                                    t1.Name="First Thread";
                                    t2.Name="Second Thread";
                                    t1.Start();
                                    t2.Start();
                                    }
                             }
                    class exp
                            {
                            public object lockme=new object();
                            public void show()
                                    {
                                    lock(lockme)
                                            {
                                            Console.WriteLine("Start "+Thread.CurrentThread.Name.ToString());
                                            Console.WriteLine("1");
                                            Console.WriteLine("2");
                                            Console.WriteLine("3");
                                            Console.WriteLine("4");
                                            Console.WriteLine("5");
                                            Console.WriteLine(Thread.CurrentThread.Name.ToString()+" Stopped");
                                            }
                                    }
                             }
            

            【讨论】:

            • 这是一个简单的同步程序
            猜你喜欢
            • 2011-04-07
            • 2017-08-07
            • 2017-07-20
            • 2014-09-23
            • 2014-07-25
            • 2012-09-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多