2013-03-28 46 views
1

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

我想这个类是静态的,作为singleton ...并锁定?

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 = "[email protected]"; 
    } // LoggerSettings 

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

} 

我想我应该实现一个双锁?没有?

我不确定最好的方法来做到这一点。请问,请帮忙吗?

谢谢你, 米格尔

+0

为什么你需要锁定?另外,静态类不能是单例。根据定义,单身人士是具有单一实例的类。根据定义,静态类没有实例。 – Pete

+2

如果你只是阅读值,为什么你需要锁定?虽然这不是你要求的:请避免单身!他们让你的代码更难以阅读和维护。看到这篇文章的一些伟大的建议:http://stackoverflow.com/questions/1300655/whats-alternative-to-singleton –

+0

虽然辛格尔顿是要走的路...这是只存储我使用的全局设置我的应用程序。那么静态会做什么?说实话,我不知道最好的方式去... –

回答

1

看看乔恩斯基特的文章Implementing the Singleton Pattern in 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 = "[email protected]"; 

} 

// Mailer settings would look similar 

如你只能在这个情况下,你不需要任何锁定读取数据。单例实例是在任何其他线程可以访问它之前创建的,因此不需要在那里锁定。

用法:

Settings.Instance.Mailer.Contact 
5

我明白了,你只能读取数据。所以你不需要在这里锁定IMO。 使用静态构造函数来初始化你的变量,比如Report(使它也是静态的)。

+0

+1给OP一个适当的建议。每个人都回答OP关于单例实现的问题真是太好了,但是你的建议(不要使用单例)更重要。 – Brian

-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; 
    } 
} 
+0

不要使用双重检查锁定,除非您在单次检查锁定时出现性能问题。双重检查锁定是危险的。 –

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 = "[email protected]"; 
    } 
} 

,并通过使用:

string x = Settings.LoggerSEttings.Report; 
10

我想有这个类的静态,如单

在C#中正确地实现一个单身,看到全碟的什么起作用和不起作用极好的总结:

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

我想我应该实现双锁?没有?

编号双重锁定锁定是一种低锁定技术,因此在弱存储器模型硬件上非常危险。当你从“幸运”模式中散步时,你已经放弃了对该计划行为的所有希望。

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

  • 是否有广泛的经验证据是单检查锁定生产性能差?
  • 假设单一检查的性能是不可接受的。由于争用,单选锁定通常会导致性能不佳,因此第一步是消除的争用。你能消除争用并获得可接受的性能吗?如果不可能删除竞争,或者如果的性能问题是由于获得无限制锁需要几个纳秒而引起的,我只会使用双重检查锁定。在后一种情况下:哇,这是一个快速的程序,那些毫微秒是最慢的东西,哇,你有非常严重的性能要求,如果你在计算单个纳秒
  • 假设单次检查的性能不可接受,无法修复。 是否有另一种低锁定技术,如使用Interlocked.CompareExchangeLazy<T>,它具有可接受的性能?至少您知道CompareExchange和Lazy<T>是由专家编写的,并在所有硬件上正确执行内存屏障。如果已经实施了更好的工具,不要使用双重检查锁定。
  • 假设这些工具都没有提供可接受的性能。 双重锁定是否可以提供可接受的性能?如果不是那么不要使用它