Lazy <t>和threadsafe false </t>的含义

时间:2012-03-26 17:34:15

标签: .net generics thread-safety lazy-evaluation base-class-library

在初始化期间使用Lazy<T>类和标记isThreadSafe: false有什么含义?

在懒惰需要访问实例成员而不是在类构造函数中初始化lazy的静态成员的情况下,这会在所有用法中自动需要isThreadSafe: false吗?

2 个答案:

答案 0 :(得分:5)

  

在懒惰需要访问实例成员而不是在类构造函数中初始化lazy的静态成员的情况下,这会在所有用法中自动要求isThreadSafe:false吗?

否 - isThreadSafe参数仅影响Lazy<T>中的值的创建方式。

基本上,当您将其设置为false时,创建值的方法只会创建值,将其设置为内部存储,然后返回值。

如果将其设置为true,则创建将包含在lock内,从而阻止多个线程创建对象。这映射到LazyThreadSafetyMode.ExecutionAndPublication

您还可以明确指定PublicationOnly,这将允许创建多个值,但在内部使用Interlocked.CompareExchange而不是锁定,以确保第一个完成的创建例程的值是用于对象的那个。

请注意,这些选项都不会对使用哪些成员计算值产生任何影响 - 它们只影响值本身的创建方式。除了创建之外的所有内容的访问始终是线程安全的。如果您在类构造函数中初始化Lazy<T> 实例成员,则可以有效地保证不需要同步,因此您可以将isThreadSafe设置为false - 但这也意味着在这种情况下绝对没有理由使用Lazy<T>,因为你正在使用显式实例化......

答案 1 :(得分:2)

来自MSDN

  

某些Lazy<T>构造函数具有名为Boolean的{​​{1}}参数,用于指定是否将从多个线程访问isThreadSafe属性。 如果您打算只从一个线程访问该属性,请传入Value以获得适度的性能优势。如果您打算从多个线程访问该属性,请传入false以指示true实例正确处理一个线程在初始化时抛出异常的竞争条件。

你写了......

  

在懒惰需要访问实例成员而不是在类构造函数中初始化lazy的静态成员的情况下,这会在所有用法中自动要求isThreadSafe:false吗?

不,它与实例与静态无关。它与是否在多个线程上访问初始化延迟的值有关。如果将在多个线程上访问它,请使用Lazy<T>以便true为您处理竞争条件。如果不是,请使用Lazy<T>以便false避免锁定,这会给你带来非常轻微的几乎无法察觉的性能提升(采取无争议的锁定非常快)。