[英]thread-safe loading of a static collection
我有一些静态的Dictionary对象为我保存一些常量列表,因此我不必在每次我的网站加载时都从数据库中加载它们(例如:国家列表,类别列表)。
因此,我有一个静态函数,该函数检查实例是否为null,是否正在查询数据库,实例化静态变量,并用数据填充它。
由于这是一个网站,因此有可能会有一个以上的人试图同时访问该信息,而对象为null,那么所有这样做的人都会同时调用该过程(这实际上不是必需的) ,会导致对数据库的不必要查询,并可能导致列表中的对象重复。
我知道有一种方法可以使这种加载线程安全(只是不太确定如何)-有人可以指出我正确的方向吗? 我应该使用锁吗?
谢谢
更新二:
这就是我写的(这是一个很好的线程安全代码吗?)
private static Lazy<List<ICountry>> _countries = new Lazy<List<ICountry>>(loadCountries);
private static List<ICountry> loadCountries()
{
List<ICountry> result = new List<ICountry>();
DataTable dtCountries = SqlHelper.ExecuteDataTable("stp_Data_Countries_Get");
foreach (DataRow dr in dtCountries.Rows)
{
result.Add(new Country
{
ID = Convert.ToInt32(dr["CountryId"]),
Name = dr["Name"].ToString()
});
}
return result;
}
public static List<ICountry> GetAllCountries()
{
return _countries.Value;
}
如果使用的是.NET 4.0,则可以使用内置的Lazy泛型类。
private static Lazy<YourObject> data = new Lazy<YourObject>(YourInitializationFunction);
public static YourObject Data { get { return data.Value; } }
请注意,必须在定义该类的类中添加静态构造函数,否则它不是完全线程安全的。
如果您不在.NET 4.0+上,则可以编写自己的代码。 基本模式如下所示:
private static YourObject data;
private static object syncObject = new object();
public static YourObject Data
{
get
{
if (data == null)
{
lock (syncObject)
{
if (data != null)
return data;
var obj = new YourObject();
return (YourObject)Interlocked.Exchange(ref data, obj);
}
}
return data;
}
}
您可以使用Lazy以惰性和线程安全的方式加载资源:
Lazy<List<string>> countries =
new Lazy<List<string>>(()=> /* get your countries from db */);
更新:
public static class HelperTables
{
private static Lazy<List<ICountry>> _countries;
static HelperTables //Static constructor
{
//Instantiating the lazy object in the static constructor will prevent race conditions
_countries = new Lazy<List<ICountry>>(() =>
{
List<ICountry> result = new List<ICountry>();
DataTable dtCountries = SqlHelper.ExecuteDataTable("stp_Data_Countries_Get");
foreach (DataRow dr in dtCountries.Rows)
{
result.Add(new Country
{
ID = Convert.ToInt32(dr["CountryId"]),
Name = dr["Name"].ToString()
});
}
return result;
});
}
public static List<ICountry> GetAllCountries()
{
return _countries.Value;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.