属性上的单一实例和实例锁定

本文关键字:实例 锁定 单一 属性 | 更新日期: 2023-09-27 18:31:11

我将创建一个将用作全局应用程序配置的类。此类应如下所示:

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 属性线程安全。

属性上的单一实例和实例锁定

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

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

虽然它可能不适用于AesCipher,但这说明了"一般解决方案"。

不要使用静态_instanceLock锁对实例成员(如 Cipher )执行锁定。_instanceLock锁旨在保护单例的创建。使用不同的锁在 Cipher 属性中执行锁定。避免将一把锁用于多种用途。不同的目的...不同的锁。

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

另外,你真的需要在这里使用ReaderWriterLockSlim吗?在大多数情况下,它实际上比普通的旧lock慢。更进一步,您是否真的需要使用双重检查锁定模式。有时它是适当的,有时它是矫枉过正的。查看 Jon Skeet 在 C# 中的单例实现模式,了解更多信息。