我有一些只读数据,我想要初始化,然后以线程安全方式定期重新初始化。对于初始化,我拉入了Joe Duffy的LazyInit and LazyInitOnceOnly structs as detailed in his blog,它使用了Double-Checked锁定模式。所以我目前执行的吸气剂只是环绕他LazyInitOnceOnly.Value
财产,给定的时间进行检查增值空间:线程安全共享对象到期和重新初始化
因此,代码如下:
public class MyData {
public DateTime TimeStamp { get; set; }
//actual shared data ommitted
public MyData() { TimeStamp = DateTime.Now; }
}
public SharedDataContainer
{
//data to be initialised thread-safe, and shared.
//assume delegate passed on construction simply 'new's the object,
private LazyInitOnceOnly<MyData> _sharedDataInit;
//receives the result from the _sharedDataInit.Value property
private MyData _sharedData;
//time-out and reinitialise after 24 hours
private TimeSpan _timeOut = new TimeSpan(24,0,0);
public MyData SharedData
{
get{
//slight adaptation of the use of the LazyInitOnceOnly struct -
//because we want to replace _sharedData later after an expiry time out.
if(_sharedData == null)
_sharedData = _sharedDataInit.Value;
//need best ideas for this bit:
if((DateTime.Now - _sharedData.TimeStamp) > _timeOut)
{
ReInitialise();
}
return _sharedData;
}
}
}
当数据被确立为摆脱日期时,应该返回旧数据,但新数据应在单独的线程上准备好,并在准备就绪时进行交换 - 以免阻止调用者。从数据中的所有后续读取应该返回旧值直到更新。
所以我认为在ReInitialise()
方法排队这样的新线程:
() => {
//assume constructor pulls in all the data and sets timestamp
_sharedData = new MyData();
}
的_sharedData覆盖在该线程将原子发生,所以这是很好。但是通过这段代码,直到重建完成,所有后续读取都会尝试并触发线程重建 - 因为它们正在读取旧的_sharedData的TimeStamp属性。
确保只触发一次重建的最佳方法是什么?
所以你希望重建发生在一个新的,衍生出来的后台工作线程和主客户线程上,以便直接返回**旧**数据(即使getter知道它是旧的)直到在后台线程上重建做完了??只是检查这里的要求.... – martinr 2010-01-18 12:45:39
是的,没错 - 对不起,我在我的问题中有点松了一口气!这是我的一个诅咒。 – 2010-01-18 12:51:44
已更新文本,使其更清晰一点 - 谢谢;) – 2010-01-18 12:55:42