c# – 当valueFactory有副作用时,ConcurrentDictionary.GetOrAdd
发布时间:2020-12-15 23:43:49 所属栏目:百科 来源:网络整理
导读:我试图通过为一些非常核心的函数引入缓存层来从我的数据库服务器卸载工作,这些函数将值插入数据库中的表并检索id.这是一个多线程环境. 我的第一个方法是: public class Cache { private Dictionarystring,Int64 i; public void Init() { /* init i with val
我试图通过为一些非常核心的函数引入缓存层来从我的数据库服务器卸载工作,这些函数将值插入数据库中的表并检索id.这是一个多线程环境.
我的第一个方法是: public class Cache { private Dictionary<string,Int64> i; public void Init() { /* init i with values from DB */ } public Int64 Get(string value) lock(i) { Int64 id; if (cache.i.TryGetValue(value,out id)) return id; id = /* Insert to DB and retrieve ID */ cache.i[value] = id; return id; } } 这有帮助.然而,线程仍然相互等待很多.我想减少这个等待时间.我的第一个想法是使用ConcurrentDictionary.GetOrAdd(key,valueFactory).这不起作用,因为可以多次调用valueFactory. 我已经结束了这种方法: public class Cache { private ConcurrentDictionary<string,Int64> i; public void Init() { /* init i with values from DB */ } public Int64 Get(string value) { Int64 id; if (i.TryGetValue(value,out id)) return id; lock (i) { if (i.TryGetValue(value,out id)) return id; id = /* Insert to DB and retrieve ID */ i.TryAdd(value,id); return id; } } 有没有更好的方法呢?这是否是线程安全的? 解决方法
你要做的是懒洋洋地创建一个需要创建的对象不超过一次,然后创建后由任意数量的线程访问. Lazy就是为此而设计的:
public class Cache { private ConcurrentDictionary<string,Lazy<long>> i; public void Init() { /* init i with values from DB */ } public Int64 Get(string value) { return i.GetOrAdd(value,new Lazy<long>(() => CreateDatabaseRecordAndGetId())) .Value; } private long CreateDatabaseRecordAndGetId() { throw new NotImplementedException(); } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |