单身人士和实例锁定属性

时间:2013-09-13 19:45:07

标签: c# multithreading thread-safety singleton

我即将创建一个我将用作全局应用程序配置的类。这个类应该是这样的:

public class GlobalConfiguration
    {    
    private static volatile GlobalConfiguration _current;
    private static ReaderWriterLockSlim _instanceLock = new ReaderWriterLockSlim();
    public ICipher Cipher {get;set;}
    public IHasher Hasher {get;set;}
    //....

    public static GlobalConfiguration Current
    {
        get
        {
            if (_current == null)
            {
                _instanceLock.EnterWriteLock();
                if (_current == null) _current = new GlobalConfiguration();
                _instanceLock.ExitWriteLock();
            }
            return _current;
        }
    }
}

现在我希望能够做到以下几点:

GlobalConfiguration.Current.Cipher = new AesCipher();

我现在担心的是,即使我的GlobalConfiguration类设计为单例,Cipher属性会发生什么? _instanceLock用于GlobalConfiguration类,但我不确定如何使用它来使Cipher属性线程安全。

2 个答案:

答案 0 :(得分:2)

除了Brian Gideon的回答:请记住,锁定对Cipher属性的访问权限不会限制对此属性设置的实例成员的访问。

如果您需要以类似Cipher的方式在多线程环境中操作GlobalConfiguration.Current.Cipher.DoSomething()属性的值,请确保同时锁定对DoSomething()的访问权限(从在AesCipher内。或者,如果可以的话,最好使AesCipher不可变。

虽然它可能不适用于AesCipher,但这个帐户是“一般解决方案”。

答案 1 :(得分:1)

不要使用静态_instanceLock锁来对Cipher等实例成员执行锁定。 _instanceLock锁用于保护单例的创建。使用其他锁定在Cipher属性中执行锁定。避免将一个锁用于多种用途。不同的目的......不同的锁。

实际上,这是非常标准的建议。使用静态锁定机制意味着同一应用程序域中同一类的所有实例必须竞争锁。在没有引用静态成员的情况下在实例属性中执行此类操作可能会产生大量不必要的锁争用。

另外,你真的需要在这里使用ReaderWriterLockSlim吗?在大多数情况下,它实际上比普通的lock慢。更进一步,你真的需要使用双重检查锁定模式。有时它是适当的,它们是时候它是矫枉过正的。有关详细信息,请查看Jon Skeet's singleton implementation patterns in C#