之前写了一篇:无缝的缓存读取:双存储缓存策略,其中使用了两个存储地址交替提供缓存数据。
在其中用了两个存储指针转换以达到无缝读取缓存,在Cat Chen一语提醒之后,想了一想:的确是没 有必要在缓存中使用两个存储指针的,其实一个存储地址,只要保证写入时在其它线程就可以。
更改存储介质至以下两个属性:
namespace CHCache {
/// <summary>
/// 缓存介质
/// </summary>
public class Medium {
/// <summary>
/// 存储区
/// </summary>
public object Store { get; set; }
/// <summary>
/// 是否正在更新
/// </summary>
public bool IsUpdating { get; set; }
}
}
这里存储区用于存储要缓存的实体内容,而IsUpdating则标识其是否正在更新。
对于缓存类,则更改了写入和读取方式。
/*
* http://www.cnblogs.com/chsword/
* chsword
* Date: 2009-3-31
* Time: 17:00
*
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
namespace CHCache {
/// <summary>
/// 双存储的类
/// </summary>
public class DictionaryCache : IEnumerable {
/// <summary>
/// 在此缓存构造时初始化字典对象
/// </summary>
public DictionaryCache() {
Store = new Dictionary<string, Medium>();
}
public void Add(string key, Func<object> func) {
if (Store.ContainsKey(key)) {//修改,如果已经存在,再次添加时则采用其它线程
var elem = Store[key];
if (elem.IsUpdating) return; //正在写入未命中
var th = new ThreadHelper(elem, func);
var td = new Thread(th.Doit);
td.Start();
}
else {//首次添加时可能也要读取,所以要本线程执行
Console.WriteLine("Begin first write");
Store.Add(key, new Medium { Store = func() });
Console.WriteLine("End first write");
}
}
/// <summary>
/// 读取时所用的索引
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public object this[string key] {
get {
if (!Store.ContainsKey(key)) return null;
var elem = Store[key];
return elem.Store;
}
}
Dictionary<string, Medium> Store { get; set; }
public IEnumerator GetEnumerator() {
return ((IEnumerable)Store).GetEnumerator();
}
}
}