繁体   English   中英

对多种方法使用相同的锁

[英]Using the same lock for multiple methods

到目前为止,我没有遇到任何问题使用相同的锁定多种方法,但我想知道以下代码是否可能实际上有问题(性能?),我不知道:

private static readonly object lockObj = new object();

public int GetValue1(int index)
{
    lock(lockObj)
    {
        // Collection 1 read and/or write
    }
}

public int GetValue2(int index)
{
    lock(lockObj)
    {
        // Collection 2 read and/or write
    }
}

public int GetValue3(int index)
{
    lock(lockObj)
    {
        // Collection 3 read and/or write
    }
}

无论如何,3种方法和集合都没有关系。

另外,如果这个lockObjlockObj例使用(在Instance属性中)会有问题吗?

编辑:澄清我在Singleton类中使用相同锁对象的问题:

private static readonly object SyncObject = new object();

public static MySingleton Instance
{
    get
    {
        lock (SyncObject)
        {
          if (_instance == null)
          {
              _instance = new MySingleton();
          }
        }
        return _instance;
    }
}

public int MyMethod()
{
      lock (SyncObject)
      {
           // Read or write
      }  
}

这会引起问题吗?

如果方法与您所说的无关,则为每个方法使用不同的锁; 否则效率很低(因为没有理由让不同的方法锁定同一个对象,因为它们可以安全地同时执行)。

而且,似乎这些是锁定在静态对象上的实例方法 - 这是有意的吗? 我有一种感觉,这是一个错误; 实例方法应该(通常)只锁定实例字段。

关于Singleton设计模式:

虽然锁定对于那些人来说是安全的,但更好的做法是对字段进行延迟初始化,如下所示:

private static object sharedInstance;
public static object SharedInstance
{
     get
     {
          if (sharedInstance == null)
              Interlocked.CompareExchange(ref sharedInstance, new object(), null);
          return sharedInstance;
     }
}

这种方式更快一些(因为互锁方法更快,并且因为初始化延迟),但仍然是线程安全的。

通过使用相同的对象来lock所有这些方法,您将序列化所有线程中对代码的所有访问

那就是......运行GetValue1()代码将阻止不同线程中的其他代码运行GetValue2()直到完成为止。 如果你添加更多锁定在同一个对象实例上的代码,那么在某些时候你最终会得到一个有效的单线程应用程序。

共享锁可锁定其他不相关的调用

如果使用相同的锁,则锁定一个方法也会不必要地锁定其他方法。 如果他们根本不相关,那么这是一个问题,因为他们必须等待彼此。 他们不应该这样做。

瓶颈

当经常调用这些方法时,这可能会造成瓶颈。 使用单独的锁定它们可以独立运行,但共享相同的锁定意味着它们必须等待锁定根据需要更频繁地释放(实际上是经常的三倍 )。

要创建线程安全的单例,请使用此技术
你不需要锁。

通常,每个锁应尽可能少地使用。
更多的方法锁定同一个东西,当你真的不需要时,你可能最终会等待它。

好问题。 制作锁具的优点和缺点是粗粒度更粗粒度,一个极端是每个数据的单独锁定,另一个极端是整个程序的一个锁定。 正如其他帖子指出的那样,重用相同锁的缺点通常是你可能会获得更少的并发性(虽然它取决于具体情况,你可能不会得到更少的并发)。

但是,使用更多锁的缺点通常是更容易造成死锁。 有更多的方法来解决死锁,你所涉及的锁越多。 例如,在不同的线程中以相反的顺序同时获取两个锁是潜在的死锁,如果只涉及一个锁则不会发生这种死锁。 当然,有时您可以通过将一个锁分成两个来修复死锁,但通常更少的锁意味着更少的死锁。 还增加了拥有更多锁的代码复杂性。

通常,这两个因素需要平衡。 为方便起见,每个类使用一个锁是很常见的,如果它不会导致任何并发问题。 实际上,这样做是一种称为监视器的设计模式。

我想说最好的做法是为了简化代码而减少锁定,并在有充分理由的情况下进行额外的锁定(例如并发,或者更简单或修复死锁的情况)。

暂无
暂无

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

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