这是否是C#中lock关键字的有效使用?

时间:2010-08-04 02:08:17

标签: singleton locking

我在ASP.NET应用程序中有一个单例类AppSetting,我需要检查一个值并选择更新它。我知道我需要使用锁定机制来防止多线程问题,但有人可以验证以下是一种有效的方法吗?

private static void ValidateEncryptionKey()
{
  if (AppSetting.Instance.EncryptionKey.Equals(Constants.ENCRYPTION_KEY, StringComparison.Ordinal))
  {
    lock (AppSetting.Instance)
    {
      if (AppSetting.Instance.EncryptionKey.Equals(Constants.ENCRYPTION_KEY, StringComparison.Ordinal))
      {
        AppSetting.Instance.EncryptionKey = GenerateNewEncryptionKey();
        AppSetting.Instance.Save();
      }
    }
  }
}

我也看到了锁定当前类中私有字段的示例,但我认为上述方法更直观。

谢谢!

1 个答案:

答案 0 :(得分:4)

直观,也许,但这些示例锁定私有字段的原因是确保应用程序中的其他任何代码都不会以使应用程序死锁的方式获取相同的锁定,这始终是良好的防御性实践

如果它是一个小应用程序,并且你是唯一一个处理它的程序员,你可能可以逃脱锁定公共字段/属性(我认为AppSetting.Instance是?),但在任何其他情况下,我强烈建议你去私人田间路线。它将保存你将来的大量调试时间,或者你将来忘记了这个位的实现细节,在AppSetting.Instance中锁定代码远处的某个地方一切都开始崩溃。

我还建议你失去最外面的。锁定并不是免费的,当然,它比进行字符串比较要快得多,特别是因为你需要在锁内第二次这样做。

所以,比如:

private object _instanceLock = new object () ;

private static void ValidateEncryptionKey()
{
  lock (AppSetting.Instance._instanceLock)
  {
    if (AppSetting.Instance.EncryptionKey.Equals(Constants.ENCRYPTION_KEY, StringComparison.Ordinal))
    {
      AppSetting.Instance.EncryptionKey = GenerateNewEncryptionKey();
      AppSetting.Instance.Save();
    }
  }
}

根据您的要求,使EncryptionKey与AppSetting.Instance中的其他状态保持一致,另一个改进是对EncryptionKey和任何相关字段使用单独的私有锁对象,而不是锁定每次都是整个实例。