【问题标题】:Lock code section in c#c#中的锁定代码部分
【发布时间】:2013-09-25 08:22:26
【问题描述】:

我的问题可能听起来像这里的许多其他问题,但它有一种我没有找到的味道。

我试图理解以下逻辑

一个通用对象

public class GenericClass
{
    public static void DoSomething(Object lockObj)
    {
        lock(lockObj)
        {
            // do something here
        }
    }
} 

A类

internal class A
{
    private static _aLock = new Object();

    public void Do_A_Thing()
    {
        GenericClass.DoSomething(_aLock);
    }
} 

B类

internal class B
{
    private static _bLock = new Object();

    public void Do_B_Thing()
    {
        GenericClass.DoSomething(_bLock);
    }
} 

我只是希望确认我的解释是否正确:

如果“A”类的多个线程将尝试同时访问“genericClass”方法“DoSomething”中的代码,则该方法将被锁定到除一个“A”类实例之外的所有实例。但是“B”类的单个实例将能够随时继续执行。如果“B”类也将执行多个实例,则它们不会干扰“A”类锁。

根据您在上面看到的情况,这是正确的吗?

【问题讨论】:

  • 是的...虽然结构看起来有点吓人
  • lock(lockObj); 的末尾真的有; 吗?你不应该。这就像拥有if (someCondition); { // do stuff }:您只是将lockif 应用于; 指示的空语句,而不是{ } 指示的代码块。
  • 通常你希望你的锁定对象是私有的,这样你就知道没有其他人可以锁定它们。传递它们需要调用者的大量信任(和知识)。
  • @Tim S.,这里的语法并不重要。认为这是一个伪代码
  • @Niall Connaughton:我的锁对象是private。他们也是static。因为我希望相同类型的实例“玩得很好”。但同时,让不同类型的实例在它们自己之间播放。代码是伪代码。真实的GenericClass.DoSomething(_aLock) 将更像GenericClass.DoSomething(key, data, _aLock);。每种不同的类型都有它的键 :o))

标签: c# .net


【解决方案1】:

是的,您的描述听起来很正确。传递锁对象in 可能有点不寻常,但它会正常工作。我建议的唯一更改是将static 字段设置为readonly,这样您就不会意外地将值更改为不同的object 引用。

【讨论】:

    【解决方案2】:

    您的结论是正确的,但传递锁定的对象并不是一个好习惯。我建议将lock 分别放在 A 类和 B 类中。

    我建议写:

    internal class A
    {
        private static readonly _aLock = new Object();
    
        public void Do_A_Thing()
        {
            lock (_aLock)
            {
                GenericClass.DoSomething();
            }
        }
    } 
    

    您是否有特定的理由将锁放在另一个类中?也许你可以用不同的方式解决你的问题?

    另外请记住,在某些情况下,可能不是您的情况,如果 A 类和 B 类相互调用(A->B->A),您可能会出现死锁。

    【讨论】:

    • 您所建议的是我使用了数百次的典型情况。现在的问题是我希望泛型类是……泛型的。它应该存储和检索某些对象所需的一些缓存。但是每个对象都有自己的缓存。而且我希望每种类型的实例不超过一个来检索或存储数据。一种解决方案是继承具有缓存功能的基础对象。但现在这是不可能的。看来我的想法得到了证实。
    • GenericClass<T>,锁对象是否会被T锁定?因为那时,您可以在GenericClass<T> 中声明private static readonly object _lockObject = new object();,这将为每个T 提供不同的锁定对象。
    【解决方案3】:

    是的,没错。 A 中的锁和B 中的锁完全不知道彼此。只有当有另一个线程使用与标识符相同的对象锁定它时,代码才会被阻塞。

    【讨论】:

      【解决方案4】:

      如果您使用的是泛型,那么类似

      public class MyGadget<T>
      {
        static readonly SyncRoot = new object() ;
      
        public T SynchronizedMethod()
        {
           lock ( SyncRoot )
           {
              SynchronizedMethodGuts() ;
           }
        }
      
      }
      

      应该做你想做的,因为MyGadget&lt;Foo&gt;MyGadget&lt;Bar&gt;不同的类:它们都有自己的、不同的SyncRoot 字段。

      【讨论】:

      • 这是一个有趣的想法,甚至可能适用于我的情况。不同的是,我的“通用”只知道如何执行某些操作,不需要实例。这里我需要一个实例。我只是认为,这对我来说太过分了,而不是 .Net 泛型的真正原因。
      猜你喜欢
      • 1970-01-01
      • 2018-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-01
      • 2023-03-16
      • 2016-11-13
      • 1970-01-01
      相关资源
      最近更新 更多