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

C# 并发使用时静态类中的静态属性,c#,static-members,static-class,C#,Static Members,Static Class,我有一个静态类“Logger”,其公共属性名为“LogLevels”,如下面的代码所示 public class Logger { private static readonly System.Object _object = new System.Object(); private static List<LogLevel> _logLevels = null; private static List<LogLevel> LogLevels

我有一个静态类“Logger”,其公共属性名为“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;
        }
    }
}
当属性在多用户或多线程环境中同时使用时,是否会导致问题

我是否需要对属性“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;
        }
    }
}
公共类记录器
{
私有静态列表_logLevels=null;
公共静态列表日志级别
{
收到
{
如果(_logLevels==null)
{
_logLevels=新列表();
if(!string.IsNullOrWhiteSpace(System.Configuration.ConfigurationManager.AppSettings[“LogLevels”]))
{
字符串[]lls=System.Configuration.ConfigurationManager.AppSettings[“LogLevels”].Split(“,”.ToCharArray());
foreach(lls中的字符串ll)
{
_添加((LogLevel)System.Enum.Parse(typeof(LogLevel),ll));
}
}
}
如果(_logLevels.Count==0)
{
_添加(LogLevel.Error);
}
返回日志级别;
}
}
}
更新:我最终使用线程同步来解决静态类中的并发问题,如下面的代码所示

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;
        }
    }
}
公共类记录器
{
私有静态只读系统.Object _Object=new System.Object();
私有静态列表_logLevels=null;
私有静态列表日志级别
{
收到
{
//确保在多线程或多用户场景中,此代码不会出现并发问题。
锁定(_对象)
{
如果(_logLevels==null)
{
_logLevels=新列表();
如果(!string.IsNullOrWhiteSpace(System.Configuration.ConfigurationManager.AppSettings[“SimpleDBLogLevelsLogger”]))
{
字符串[]lls=System.Configuration.ConfigurationManager.AppSettings[“SimpleDBLogLevelsLogger”].Split(“,”.ToCharArray());
foreach(lls中的字符串ll)
{
_添加((LogLevel)System.Enum.Parse(typeof(LogLevel),ll));
}
}
}
如果(_logLevels.Count==0)
{
_添加(LogLevel.Error);
}
}
返回日志级别;
}
}
}
当该属性在多用户或多线程环境中同时使用时,是否会导致问题

当然<代码>列表不是为多线程设计的,只有多个读卡器(没有写入器)的情况除外

我是否需要对属性“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;
        }
    }
}
这是一种方法。或者只是在类型初始化时初始化它,然后在它周围返回一个只读包装器。(您确实不希望多个线程对其进行修改。)


请注意,一般来说,在静态构造函数中执行大量工作是一项非常重要的任务。如果失败,对该属性的每次访问都将永远失败,您是否感到高兴?

此代码具有竞争条件,无法从多个线程安全执行。主要问题是
列表
类型不是线程安全的,但此代码将自由写入。这意味着写操作可以并行进行,因此打破了
列表的隐式约定。简短的回答是“是”,并且“是”,您确实需要线程同步。

另一个问题是,为什么要重新发明轮子?您可以使用log4net或.NET logging framework之类的工具。

您的属性是
私有的
在您的示例中,而不是
公共的
我已经更正了修饰符并将其更改为公共的。……除非没有人可以访问它(我想他是指公共的,而不是私有的)Jon-So,您的意思是要么使用线程同步,要么将属性代码传输到此类的静态构造函数。正当或者你的意思是别的?@Sunil:是的,但最重要的是返回一个只读包装器。所有这些日志框架的问题是学习曲线太陡。我希望我的开发人员从第一天开始记录日志,我只想记录到数据库。你可以慢慢来。例如,log4net的基本特性及其基本配置相对简单,即使是新手也可以在几个小时内开始使用它。或者,您可以围绕lon4net创建一个简化的包装器,它将隐藏配置的复杂性,