Mat*_*att 30 .net c# multithreading
我正在使用C#和.NEt 3.5.OptionA和OptionB有什么区别?
class MyClass
{
    private object m_Locker = new object();
    private Dicionary<string, object> m_Hash = new Dictionary<string, object>();
    public void OptionA()
    {
        lock(m_Locker){ 
          // Do something with the dictionary
        }
    }
    public void OptionB()
    {
        lock(m_Hash){ 
          // Do something with the dictionary
        }
    }       
}
我开始涉足线程化(主要是为多线程应用程序创建缓存,不使用HttpCache类,因为它没有附加到网站上),我在很多例子中都看到了OptionA语法在线看,但我不明白在OptionB上做了什么,如果有的话.
Cor*_*rch 28
选项B使用要保护的对象来创建关键部分.在某些情况下,这更清楚地传达了意图.如果一致使用,它保证一次只有受保护对象的一个关键部分处于活动状态:
lock (m_Hash)
{
    // Across all threads, I can be in one and only one of these two blocks
    // Do something with the dictionary
}
lock (m_Hash)
{
    // Across all threads, I can be in one and only one of these two blocks
    // Do something with the dictionary
}
选项A限制较少.它使用辅助对象为要保护的对象创建关键部分.如果使用多个辅助对象,则一次可以为受保护对象激活多个关键部分.
private object m_LockerA = new object();
private object m_LockerB = new object();
lock (m_LockerA)
{
    // It's possible this block is active in one thread
    // while the block below is active in another
    // Do something with the dictionary
}
lock (m_LockerB)
{
    // It's possible this block is active in one thread
    // while the block above is active in another
    // Do something with the dictionary
}
如果仅使用一个辅助对象,则选项A等同于选项B. 就阅读代码而言,选项B的意图更清晰.如果您要保护多个对象,则选项B实际上不是一个选项.
Dan*_*ted 11
要明白,锁(m_Hash)也很重要不是防止其他代码使用散列.它只能阻止其他代码运行,它也使用m_Hash作为锁定对象.
使用选项A的一个原因是因为类可能具有您将在lock语句中使用的私有变量.使用一个对象可以更容易地锁定对所有对象的访问,而不是尝试使用更精细的粒度锁来锁定对所需成员的访问.如果你尝试使用更精细的方法,你可能需要在某些情况下采取多个锁,然后你需要确保你总是以相同的顺序采取它们以避免死锁.
使用选项A的另一个原因是因为有可能在您的课程之外可以访问对m_Hash的引用.也许您有一个提供对它的访问的公共属性,或者您可能将其声明为受保护的,派生类可以使用它.在任何一种情况下,一旦外部代码引用它,外部代码就可能将其用于锁定.这也开启了死锁的可能性,因为您无法控制或知道锁将被采用的顺序.
实际上,如果您正在使用其成员,则锁定对象并不是一个好主意.Jeffrey Richter在他的书"CLR via C#"中写道,无法保证您用于同步的一类对象不会lock(this)在其实现中使用(这很有趣,但它是Microsoft推荐的同步方式......然后,他们发现这是一个错误),所以使用一个特殊的单独对象进行同步总是一个好主意.因此,正如您所看到的,OptionB不会为您提供死锁保证 - 安全性.因此,OptionA比OptionB更安全.