2013-03-01 56 views
-1

我有一个名为“LogLevels”的公共属性的静态类“Logger”,如下面的代码所示。同时使用静态类中的静态属性

当在多用户或多线程环境中同时使用该属性时,它是否会导致问题?

我需要使用线程同步作为属性“LogLevels”中的代码吗?

public class Logger 
{ 
    private static List<LogLevel> _logLevels = null; 


    public static List<LogLevel> LogLevels 
    { 
     get 
     { 
      if (_logLevels == null) 
      { 
       _logLevels = new List<LogLevel>(); 
       if (!string.IsNullOrWhiteSpace(System.Configuration.ConfigurationManager.AppSettings["LogLevels"])) 
       { 

        string[] lls = System.Configuration.ConfigurationManager.AppSettings["LogLevels"].Split(",".ToCharArray()); 
        foreach (string ll in lls) 
        { 

         _logLevels.Add((LogLevel)System.Enum.Parse(typeof(LogLevel), ll)); 
        } 
       } 
      } 

      if (_logLevels.Count == 0) 
      { 
       _logLevels.Add(LogLevel.Error); 
      } 
      return _logLevels; 
     } 
    } 
} 

更新:我结束了使用线程同步解决并发问题的一个静态类,如下面的代码。

public class Logger 
{ 
    private static readonly System.Object _object = new System.Object(); 

    private static List<LogLevel> _logLevels = null; 


private static List<LogLevel> LogLevels 
    { 
     get 
     { 
      //Make sure that in a multi-threaded or multi-user scenario, we do not run into concurrency issues with this code. 
      lock (_object) 
      { 
       if (_logLevels == null) 
       { 
        _logLevels = new List<LogLevel>(); 
        if (!string.IsNullOrWhiteSpace(System.Configuration.ConfigurationManager.AppSettings["SimpleDBLogLevelsLogger"])) 
        { 

         string[] lls = System.Configuration.ConfigurationManager.AppSettings["SimpleDBLogLevelsLogger"].Split(",".ToCharArray()); 
         foreach (string ll in lls) 
         { 

          _logLevels.Add((LogLevel)System.Enum.Parse(typeof(LogLevel), ll)); 
         } 
        } 
       } 

       if (_logLevels.Count == 0) 
       { 
        _logLevels.Add(LogLevel.Error); 
       } 
      } 
      return _logLevels; 
     } 
    } 
} 
+0

您的房产在您的示例中是“private”,而不是“public” – JerKimball 2013-03-01 18:38:08

+0

我已更正修改并将其更改为public。 – Sunil 2013-03-01 21:38:29

回答

3

当属性在多用户或多线程环境中同时使用,可它引起的问题?

绝对。 List<T>不适用于多线程,除了只是多个阅读器(无编写者)的情况。

是否需要使用属性LogLevels中代码的线程同步?

那么这是一种方法。或者只是在初始化类型时初始化它,然后返回一个只读包装器。 (你真的不希望多线程修改它。)

请注意,通常,在静态构造函数中执行大量工作是bad idea。你是否满意,如果失败了,每一次访问这个属性都会失败,直到永远?

+0

...除非没有人可以访问它(我认为他的意思是公开的,而不是私有的) – JerKimball 2013-03-01 18:38:45

+0

Jon - 所以,你说要么使用线程同步,要么将属性代码转移给这个类的静态构造函数。对?或者你的意思是别的? – Sunil 2013-03-01 18:45:53

+0

@Sunil:是的,但最重要的是返回一个只读包装。 – 2013-03-01 18:47:20

3

此代码拥有竞争条件,不能安全地从多个线程执行。主要问题是List<T>类型不是线程安全的,但此代码将自由写入。这意味着写入可以并行发生,因此打破隐式合约List<T>

1

简短答案是“是”和“是”您确实需要线程同步。另一个问题是,为什么重新发明轮子?你可以使用类似log4net或.NET日志框架的东西。

+0

所有这些日志框架的问题是陡峭的学习曲线。我希望我的开发人员从第1天开始记录,并且我只想记录到数据库。 – Sunil 2013-03-01 20:11:53

+0

你可以慢慢来。例如,log4net的基本功能及其基本配置相对简单,甚至新手也可以在几个小时内开始使用它。或者你可以在lon4net上创建一个简化的包装,这会隐藏配置的复杂性, – user1873415 2013-03-01 20:25:04