并发使用时静态类中的静态属性

时间:2013-03-01 18:35:57

标签: c# static-members static-class

我有一个静态类'Logger',其公共属性名为'LogLevels',如下面的代码所示。

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

我是否需要对属性“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;
        }
    }
}

UPDATE:我最终使用线程同步来解决静态类中的并发问题,如下面的代码所示。

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

3 个答案:

答案 0 :(得分:3)

  

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

绝对。 List<T>不是为多线程设计的,除了多个读者(没有编写者)的情况。

  

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

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

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

答案 1 :(得分:3)

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

的隐式契约

答案 2 :(得分:1)

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