c# - 两种不同场景下的锁性能

标签 c# multithreading locking thread-safety

我有一个包含 2 个内联列表的类,其中包含超过 1000 个这样的元素,

public class A
{
    private List<long> aList = new List<long>();
    private List<long> bList = new List<long>();
    void MethodThatUsesAList()
    {
      //Works with aList
    }
    void MethodThatUsesBList()
    {
      //Works with bList
    }
    void MethodThatUsesBoth()
    {
      //Works with both lists
    }
}

现在,我想让这个类线程安全,我看到有两种不同的使用锁的场景,首先是创建

object _synchObject = new object()

并在所有方法中锁定这个对象, 或第二个在使用时锁定每个列表, 我的第一个问题是,首选哪种方法? 如果首选第二个,这样使用锁是否有性能问题?

    void MethodThatUsesBoth()
    {
       lock(aList){
           lock(bList){
                 //Works with both lists
           }
       }
    }

最佳答案

这里有两个不同的问题:

  • 使用一把组合锁还是两把分离锁
  • 是使用单独的对象来锁定还是使用列表本身(或其 SyncRoot)

这些在某种程度上是可分离的——因为如果您使用两个单独的锁,您可以创建两个单独的对象来锁定,每个列表一个。

如果您希望 MethodThatUsesAListMethodThatUsesBList 能够同时运行,您将需要两个单独的锁。然后你必须确保任何时候你可能获得两个锁,你获得它们的顺序相同。这意味着对任何获取​​锁的方法中的所有代码进行推理:例如,您需要确保它不会调用获取另一个锁的另一个方法。

如果您的特定场景不太可能受到所有方法的影响,这些方法被运行任何其中的任何一个线程有效地阻塞其他线程,那么我'为了简单起见,d 使用单个锁。

无论哪种情况,我个人都会选择其他代码不知道的“私有(private)”锁。我发现以这种方式编写的代码更容易推理。使用列表本身或同步根可能绝对没问题 - 但我更愿意考虑其他任何东西都无法获得的锁。

关于c# - 两种不同场景下的锁性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4518295/

相关文章:

c# - 存储最后 N 个击键

c++ - SQLite:以 WAL 模式保留文件句柄

multithreading - 如何告诉Hotspot JVM使用单处理器还是多处理器线程同步?

concurrency - 锁、互斥量和信号量有什么区别?

c# - 如何在 C# 中替换 .docx 文件中的文本

c# - 我可以在构造函数注释中引用属性注释吗?

C# 统一错误 : Could not load file or assembly

c# - 如何杀死 C# 线程?

c++ - # 错误“线程支持不可用 : it has been explicitly disabled with BOOST_DISABLE_THREADS

database - symfony2 Doctrine 表锁