-1

我有一个静态类 '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;
        }
    }
}

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

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

3 回答 3

3

当该属性在多用户或多线程环境中并发使用时,会不会引起问题?

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

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

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

请注意,一般来说,在静态构造函数中做大量工作是个坏主意。您是否足够高兴,如果这失败了,每次对该属性的访问都将永远失败?

于 2013-03-01T18:37:56.187 回答
3

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

于 2013-03-01T18:38:49.743 回答
1

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

于 2013-03-01T18:39:52.550 回答