C# 在需要时只生成一次可缓存数据,否则会阻塞吗?

C# 在需要时只生成一次可缓存数据,否则会阻塞吗?,c#,asp.net,caching,concurrency,t4,C#,Asp.net,Caching,Concurrency,T4,我正在制作一个很酷的(imo)T4模板,它将使缓存更加容易。在制作这个模板时,我有一个选择,就是允许“加载一次”类型的功能,尽管我不确定它有多安全 基本上,我想这样做,这样你就可以做这样的事情: var post=MyCache.PostsCache.GetOrLockLoad(id, ()=>LoadPost(id)); 基本上,当必须加载缓存时,它会在PostsCache上放置一个阻塞锁。这样,其他线程将阻塞,直到LoadPost()函数完成。这使得LoadPost在每次缓存未命中时

我正在制作一个很酷的(imo)T4模板,它将使缓存更加容易。在制作这个模板时,我有一个选择,就是允许“加载一次”类型的功能,尽管我不确定它有多安全

基本上,我想这样做,这样你就可以做这样的事情:

var post=MyCache.PostsCache.GetOrLockLoad(id, ()=>LoadPost(id));
基本上,当必须加载缓存时,它会在
PostsCache
上放置一个阻塞锁。这样,其他线程将阻塞,直到
LoadPost()
函数完成。这使得LoadPost在每次缓存未命中时只执行一次。执行此操作的传统方法是,LoadPost将在缓存为空时执行,如果在第一次加载缓存之前出现多个请求,则可能会执行多次

这是一个合理的做法,还是因为这样的事情而阻塞其他线程是危险的还是浪费的?我在想,线程锁定的开销比大多数操作都要大,但也许不是

有没有人见过这样的事情,这是一个好主意还是仅仅是危险


此外,尽管它被设计为在任何缓存和应用程序类型上运行,但它最初的目标是ASP.Net的内置缓存机制

这似乎没问题,因为理论上,第一次请求之后的请求只会等待它们自己加载数据所需的时间

但是它仍然感觉有点不确定——如果第一个加载程序线程由于一些不影响其他线程的间歇性问题而被阻塞,该怎么办。感觉让每个线程独立地尝试加载会更安全

这也增加了锁定机制的复杂性和开销。请记住,执行的锁定越多,出现死锁情况的风险就越大(通常)。尽管在您的情况下,只要
LoadPost
方法中没有出现令人生厌的锁定,就不应该成为问题

考虑到风险,我认为您最好选择非锁定选项

毕竟,对于任何给定的线程,等待时间几乎是相同的——要么是加载所花费的时间,要么是等待第一个线程加载所花费的时间


当使用非并发选项而不是并发选项时,我总是感到有点不舒服,尤其是当收益似乎微乎其微时。

好吧,我将允许两个版本,但我想知道这个雄心勃勃的一次性加载是否值得实现。听起来不错,但也很危险。如果ASP.Net的缓存决定不缓存正在存储的对象(我认为这不是不可能的,但不是很可能),那么应该做什么也不是无关紧要的。我认为值得尝试一下,即使只是为了好玩,只要您还保留一个非锁定选项,以防出现问题:)Yes是众所周知的模式,例如由.NET Lazy类支持(尽管这本身不是缓存)。当示例中的.LoadPost会消耗大量资源/根据时间返回不同的结果/修改数据时,它非常有用。然而,对于其他情况,我倾向于避免使用它以提高吞吐量。@FuleSnabel有趣。这实际上是我第一次看到懒惰的东西。