1

在多线程应用程序(ASP.NET MVC)上,我需要一个全局设置类,其中包含从 Web.Config 获取的常量和值。

我想让这个类静态,作为单例......并锁定?

public static class Settings {

  public static LoggerSettings Logger;
  public static MailerSettings Mailer;

  public class LoggerSettings {
    public String Levels { get { return ConfigurationManager.AppSettings["Logger.Levels"]; } }
    public const String Report = "team@xyz.com";
  } // LoggerSettings

  public class MailerSettings {
    public String Contact { get { return ConfigurationManager.AppSettings["Mailer.Contact"]; } }
  } // MailerSettings

}

我想我应该实施双锁?不?

我不确定执行此操作的最佳方法。请问,我能得到一些帮助吗?

谢谢你,米格尔

4

5 回答 5

10

我想让这个类静态,作为单例

要在 C# 中正确实现单例,请参阅 Jon Skeet 对哪些有效和无效的出色总结:

http://cshapindepth.com/Articles/General/Singleton.aspx

我想我应该实施双锁?不?

不。双重检查锁定是一种低锁定技术,因此在弱内存模型硬件上非常危险。当您偏离“有福的”模式时,您已经放弃了对程序可预测行为的所有希望。

我会使用双重检查锁定的唯一情况是当以下所有条件都为真时:

  • 是否有大量的经验证据表明单检查锁定会产生较差的性能?
  • 让我们假设单检查性能是不可接受的。单检查锁通常会因为争用而产生不好的性能,所以第一步是消除争用。您能否消除争用并获得可接受的性能?如果无法消除争用,或者性能问题是由获得无争用锁所需的几纳秒引起的,我只会使用双重检查锁定。在后一种情况下:哇,这是一个快速程序,那些纳秒是最慢的,哇,如果你计算单个纳秒,你有非常严格的性能要求
  • 让我们假设单检查的性能是不可接受的并且无法修复。是否有另一种低锁定技术,例如使用 Interlocked.CompareExchangeLazy<T>具有可接受的性能?至少您知道 CompareExchangeLazy<T>是由专家编写的,并在所有硬件上适当地强制执行内存屏障。如果已经实现了更好的工具,请不要使用双重检查锁定。
  • 让我们假设这些工具都没有提供可接受的性能。 双重检查锁定是否提供可接受的性能?如果没有,请不要使用它
于 2013-03-28T15:11:24.967 回答
5

如我所见,您只读取数据。所以你不需要锁定这里IMO。使用静态构造函数来初始化您的变量,例如 Report(使其也是静态的)。

于 2013-03-28T13:03:40.907 回答
1

如果你喜欢它是静态的并且是单例的,试试这种方式:

public static class Settings {
  private static readonly object LockObject = new object();
  private static LoggerSetting LoggerInstance;

  public static LoggerSetting LoggerSettings {
    get {
      lock (LockObject) {
         if (LoggerInstance == null)
           LoggerInstance = new LoggerInstance(); 

         return LoggerInstance;
       }
     }
   }

   public class LoggerSetting {
     public String Levels {
       get { return ConfigurationManager.AppSettings["Logger.Levels"]; }
     } 

     public const String Report = "team@xyz.com";
   }
}

并通过以下方式使用它:

string x = Settings.LoggerSEttings.Report;
于 2013-03-28T13:24:29.353 回答
1

看看 Jon Skeet 的文章在 C# 中实现单例模式

最简单且足够好的选择:

public sealed class Settings
{
    private static readonly Settings instance = new Settings();

    public LoggerSettings Logger { get; private set; }
    public MailerSettings Mailer { get; private set; }

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static Settings()
    {
    }

    private Settings()
    {
       Logger = new LoggerSettings();
       Mailer = new MailerSettings();
    }

    public static Settings Instance { get { return instance;} }
}

public class LoggerSettings {

    public LoggerSettings()
    {
        Levels = ConfigurationManager.AppSettings["Logger.Levels"];
    }

    public String Levels { get; private set; }
    public const String Report = "team@xyz.com";

}

// Mailer settings would look similar

由于您只从该实例中读取数据,因此您不需要任何锁定。单例实例是在任何其他线程可以访问它之前创建的,因此也不需要在那里锁定。

用法:

 Settings.Instance.Mailer.Contact
于 2013-03-28T15:54:07.483 回答
-1

如果您仍然想继续并拥有一个单例实例

    public class MySettings{
    private static Object lockObj = new Object();
    private MySettings() {} // private .ctor

    private static MySettings _instance;

    public static MySettings MySingleSettings{
     get{
      if(_instance == null){
      lock(lockObj){
        if(_instance == null)
          _instance = new MySettings();
        }
      }
       return _instance;
    }
}
于 2013-03-28T13:10:02.990 回答