我有一个静态类'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;
}
}
}
答案 0 :(得分:3)
在多用户或多线程环境中同时使用该属性时,是否会导致问题?
绝对。 List<T>
不是为多线程设计的,除了只多个读者(没有编写者)的情况。
我是否需要对属性“LogLevels”中的代码使用线程同步?
那是一种方法。或者只是在类型初始化时初始化它,然后在它周围返回一个只读包装器。 (你真的不希望多个线程修改它。)
请注意,通常,在静态构造函数中执行大量工作是bad idea。你是否满意,如果失败,对这个属性的每次访问都会永远失败?
答案 1 :(得分:3)
此代码具有竞争条件,无法从多个线程安全地执行。主要问题是List<T>
类型不是线程安全的,但是这段代码可以自由写入。这意味着写入可以并行发生,因此打破了List<T>
答案 2 :(得分:1)
简短的回答是“是”和“是”你确实需要线程同步。 另一个问题是,为什么重新发明轮子?您可以使用log4net或.NET日志框架之类的东西。