C# 可以(应该?)懒惰<;T>;是否用作缓存技术?
我想使用C# 可以(应该?)懒惰<;T>;是否用作缓存技术?,c#,multithreading,caching,locking,lazy-loading,C#,Multithreading,Caching,Locking,Lazy Loading,我想使用.NET的Lazy类来实现线程安全缓存。假设我们有以下设置: class Foo { Lazy<string> cachedAttribute; Foo() { invalidateCache(); } string initCache() { string returnVal = ""; //CALCULATE RETURNVAL HERE return re
.NET
的Lazy
类来实现线程安全缓存。假设我们有以下设置:
class Foo
{
Lazy<string> cachedAttribute;
Foo()
{
invalidateCache();
}
string initCache()
{
string returnVal = "";
//CALCULATE RETURNVAL HERE
return returnVal;
}
public String CachedAttr
{
get
{
return cachedAttribute.Value;
}
}
void invalidateCache()
{
cachedAttribute = new Lazy<string>(initCache, true);
}
}
class-Foo
{
懒惰的缓存属性;
Foo()
{
失效缓存();
}
字符串initCache()
{
字符串returnVal=“”;
//在这里计算RETURNVAL
返回值;
}
公共字符串CachedAttr
{
得到
{
返回cachedAttribute.Value;
}
}
void invalidateCache()
{
cachedAttribute=newlazy(initCache,true);
}
}
我的问题是:
注意:我决定使对象线程不安全,并对对象的访问进行仔细控制。好吧,这不是线程安全的,因为一个线程在另一个线程失效后看到新值后仍然可以看到旧值-因为第一个线程可能没有看到对
cachedAttribute
的更改。从理论上讲,这种情况可能永远持续下去,尽管可能性很小:)
使用
Lazy
作为不变值的缓存对我来说似乎是一个更好的主意-更符合它的意图-但是如果您能够处理在另一个线程中使用旧的“无效”值任意长时间的可能性,我想这没问题。cachedAttribute是一个共享资源,需要防止并发修改
用锁保护它
:
private readonly object gate = new object();
public string CachedAttr
{
get
{
Lazy<string> lazy;
lock (gate) // 1. Lock
{
lazy = this.cachedAttribute; // 2. Get current Lazy<string>
} // 3. Unlock
return lazy.Value // 4. Get value of Lazy<string>
// outside lock
}
}
void InvalidateCache()
{
lock (gate) // 1. Lock
{ // 2. Assign new Lazy<string>
cachedAttribute = new Lazy<string>(initCache, true);
} // 3. Unlock
}
private readonly object gate=new object();
公共字符串CachedAttr
{
得到
{
懒惰;
锁(门)//1.锁
{
lazy=this.cachedAttribute;//2.获取当前lazy
}//3.解锁
返回lazy.Value//4.获取lazy的值
//外锁
}
}
void InvalidateCache()
{
锁(门)//1.锁
{//2.分配新任务
cachedAttribute=newlazy(initCache,true);
}//3.解锁
}
或使用:
void InvalidateCache()
{
Exchange(ref cachedAttribute,new Lazy(initCache,true));
}
volatile
在这种情况下也可以工作,但它会让我头疼。是的,无效值在这种情况下并不好(至少不是任意长的值)。谢谢。我建议将cachedAttribute
的检索放在锁中,但让Value
的计算在锁外进行。谢谢您的快速回答。多线程让我头疼,所以别担心,如果你的担心是不稳定的,那你就有好朋友了!这两种情况中的任何一种都会阻止读取旧值吗?@Cpfohl:不会,我的答案只是阻止同时修改cachedAttribute
。@Jon Skeet提出的问题依然存在。
void InvalidateCache()
{
Interlocked.Exchange(ref cachedAttribute, new Lazy<string>(initCache, true));
}