我有一个实现单例模式的类,如下所示:
public class SearchSingletonObject
{
private static SearchSingletonObject foundation = null;
public SearchObject Object= null;
private static StringCollection views = null;
private static object control = new object();
public IEnumerable<string> blacklist = null;
public static void ClearFoundation()
{
foundation = null;
}
public static SearchSingletonObject Foundation
{
get
{
if (foundation == null)
{
lock (control)
{
if (foundation == null)
{
foundation = new SearchSingletonObject();
var blacks = File.ReadAllText(HostingEnvironment.ApplicationPhysicalPath + "\\blacklist.txt");
foundation.blacklist = blacks.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries).Where(x => !string.IsNullOrEmpty(x) || x != " ");
views = new StringCollection();
var items = ConfigurationManager.AppSettings["SearchView"].Split(',');
foreach (var item in items)
{
views.Add(item);
}
foundation.Object = new SearchObject(ConfigurationManager.AppSettings["ContentDistributor"],
ConfigurationManager.AppSettings["Port"],
views);
}
}
}
return foundation;
}
}
public SearchSingletonObject()
{
}
}
我们在wcf休息服务中使用此类。但是在非周期性间隔中,我们得到“Value not not null”错误。这是我的日志文件:
08.03.2011 11:40:39 ERROR Message : Value cannot be null.
Parameter name: source
StackTrace : at System.Linq.Enumerable.Where[TSource](IEnumerable`1 source, Func`2 predicate)
at Search.Service.SearchService.Search(String keyword, Int32 offset, Int32 hit, String navstate, String username, Boolean issecure, Int32 suggest, String sortref, String fields, Int32 IsFirstSearch, String misspelled, String category) in D:\tfs\Hey\HeyRestApi\HeyService\HeyService.cs:line 68
日志文件提到我服务中的下面一行:
var blacks = SearchSingletonObject.Foundation.blacklist.Where<string>(x => item.Equals(x)).FirstOrDefault();
奇怪的是,“黑名单”对象获得空值。出错后,我们必须重置IIS,以使应用程序正常工作。我们无法在本地服务器上重现错误。它恰好发生在我们的客户生产环境中。
我们如何解决这个问题以及这个奇怪错误的原因是什么?
提前致谢,
答案 0 :(得分:2)
Double-checked locking is broken
简短说明:
即使foundation
非空,没有锁定,您也无法确定基金会的成员从处理器的角度来看是非空的。
您需要删除锁定之外的if语句。
<强>更新强>
更好的解决方案是将基础标记为易变的:
private static volatile SearchSingletonObject foundation = null;
The need for volatile modifier in double checked locking in .NET有更多详情。