设想
假设我们有:
var dictionary = new ConcurrentDictionary<string, Lazy<Heavy>>();
实例化
Heavy
非常消耗资源。让我们考虑一下这段代码:return dictionary.GetOrAdd("key", key =>
{
return new Lazy<Heavy>(() =>
{
return Instantiate();
});
}).Value;
Instantiate()
方法当然会返回一个 Heavy
类型的实例。问题
对于给定的键,是否 100% 保证方法
Instantiate()
最多将被调用一次 ?来源
有人声称拥有多个线程,我们只能创建
Lazy<Heavy>
的多个实例,这非常便宜。实际的方法 Instantiate()
最多会被调用一次。我个人的印象是,这是错误的。真相是什么?
最佳答案
Instantiate
确实只会执行一次。 GetOrAdd
的文档说:
这意味着:即使 addValueFactory
多次运行 - 只有一个返回值实际上会被添加到字典中并从 GetOrAdd
调用返回。因此,如果两个线程同时使用相同的键调用 GetOrAdd
- 创建了 2 个 Lazy<Heavy>
实例,但只有 1 个实例被添加到字典中并从两个 GetOrAdd
调用返回,另一个将被丢弃(因此,即使工厂已经运行 -这并不意味着该工厂提供的值是最终从 GetOrAdd
返回的值)。因为你在 .Value
的结果上调用 GetOrAdd
- 你总是在 Lazy<Heavy>
的单个实例上调用它,所以 Instantiate
总是最多运行一次。
关于c# - ConcurrentDictionary + Lazy -- 实例化只会发生一次吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47489211/