C# 锁定私有对象还是哈希集本身?

C# 锁定私有对象还是哈希集本身?,c#,locking,C#,Locking,假设我有下面的hashset HashSet<string> hsWaitingToBeFetched = new HashSet<string>(); 或 不会有性能差异1。。语义上的区别在于,如果HashSet被公开,其他一些代码也会锁定它 我认为在这种情况下使用单独的锁对象更为明显: 更清晰的意图-取决于场景 可以隐藏锁对象(private)但公开HashSet这一点应该忽略不计,不需要非常仔细地考虑-仅为(private)更新(public)HashSet

假设我有下面的hashset

   HashSet<string> hsWaitingToBeFetched = new HashSet<string>();

不会有性能差异1。。语义上的区别在于,如果HashSet被公开,其他一些代码也会锁定它

我认为在这种情况下使用单独的锁对象更为明显:

  • 更清晰的意图-取决于场景
  • 可以隐藏锁对象(private)但公开HashSet这一点应该忽略不计,不需要非常仔细地考虑-仅为(private)更新(public)HashSet而锁定未正确同步
  • 如果类型锁定自身,请避免意外
  • 即使在重新分配HashSet成员时也可用
  • 但是,由于单独的lock对象不会锁定HashSet,因此如果其他对象预期它会锁定


    1新锁对象创建成本可忽略。对于上述两种情况,CLR以相同的方式进入监视器。

    不会有性能差异1。。语义上的区别在于,如果HashSet被公开,其他一些代码也会锁定它

    我认为在这种情况下使用单独的锁对象更为明显:

  • 更清晰的意图-取决于场景
  • 可以隐藏锁对象(private)但公开HashSet这一点应该忽略不计,不需要非常仔细地考虑-仅为(private)更新(public)HashSet而锁定未正确同步
  • 如果类型锁定自身,请避免意外
  • 即使在重新分配HashSet成员时也可用
  • 但是,由于单独的lock对象不会锁定HashSet,因此如果其他对象预期它会锁定



    1新锁对象创建成本可忽略。CLR在两种情况下以相同的方式进入监视器。

    如果您需要知道哪个性能更高,则应该考虑尝试和测量两种情况。请注意,选择要锁定的对象更多的是从程序正确性的角度,而不是从性能的角度来看。哈希集是私有的吗?是否有过哈希集本身发生变化的情况?也就是说,您是否改变了引用集合的变量的值,还是仅仅改变了集合的内容?您可以使用<代码> CONTURNCE字典,简单地忽略<代码>值< />代码>如果您需要知道哪个更具有性能,则应该考虑尝试和测量两者。请注意,选择要锁定的对象更多的是从程序正确性的角度,而不是从性能的角度来看。哈希集是私有的吗?是否有过哈希集本身发生变化的情况?也就是说,您是更改引用集合的变量的值,还是只更改集合的内容?您可以使用
    ConcurrentDictionary
    ,只需忽略
    我不理解第2点。如果你公开的是散列集而不是锁对象,那么你公开的代码如何安全地使用它?@EricLippert感谢你的挑战-我无法想出任何不复杂的用例,并且已经删除了该项。(我确信我在写它的时候想到了一个好点子,但回顾一下,它似乎被误导了。)通常的情况是,你想同时暴露一个对象并拥有一个与之相关联的锁,这在你的第三项中得到了暗示:当逻辑上被锁定的对象的类型为
    类型时。不公开一个类型可能非常困难,因此锁定的对象应该是私有的,以确保只有类型内部的代码会锁定自身。如果你公开的是散列集而不是锁对象,那么你公开的代码如何安全地使用它?@EricLippert感谢你的挑战-我无法想出任何不复杂的用例,并且已经删除了该项。(我确信我在写它的时候想到了一个好点子,但回顾一下,它似乎被误导了。)通常的情况是,你想同时暴露一个对象并拥有一个与之相关联的锁,这在你的第三项中得到了暗示:当逻辑上被锁定的对象的类型为
    类型时。不公开类型可能非常困难,因此锁定的对象应该是私有的,以确保只有类型内的代码才锁定自身。
    
    private Object lockHashset = new Object();
    lock(lockHashset)
    {
    // do stuff here
    }
    
    lock(hsWaitingToBeFetched)
    {
    // do stuff here
    }