2012-03-26 23 views
2

在初始化过程中使用Lazy<T>类和标记isThreadSafe: false会产生什么影响?惰性<T>和线程安全错误的含义

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

回答

4

在这样一个场景,懒惰需要访问实例成员,并在那里懒惰是类的构造函数自动执行此操作需要isThreadSafe内未初始化的静态成员:在所有使用假的?

否 - isThreadSafe参数只影响如何Lazy<T>内的值被创建。

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

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

还可以指定PublicationOnly明确,这将允许创建不止一个值,但随后使用Interlocked.CompareExchange内部,而不是一个锁,以确保第一完成创建例程的价值是所使用的对象之一。

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

+0

既然你声明,不需要明确使用'isThreadSafe:false',什么会导致http://stackoverflow.com/questions/6300398/invalidoperationexception-in-my-lazy-value-factory in在我的Lazy用法中访问实例属性的场景?在初始化懒惰的代码中没有错误,代码是彻底的单元测试,只有移到懒惰,以避免重复执行。 – 2012-03-26 17:52:37

+0

@ChrisMarisic如果您在Lazy 的初始化函数中引发异常,您会得到该异常。检查内部异常的原因为什么 - 但是在初始化阶段引发了异常。 – 2012-03-26 18:06:02

+0

由于访问实例成员并不特别要求添加isThreadSafe:false或等效的Enum值,并且没有由我的工厂代码生成异常,所以我必须同意@Jacob http://stackoverflow.com/a/6510343/ 37055在懒惰中有某种奥术缺陷。我刚刚删除了Lazy的用法,并使用'get {return _val? (_val = CreateVal())}'。 – 2012-03-26 18:38:14

2

MSDN

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

你写...

在这样一个场景,懒惰需要访问实例成员,而不是静态成员在慵懒的类的构造函数初始化里面这是否自动要求isThreadSafe:在全是假的用法?

不,它与实例与静态无关。它与被初始化的延迟值是否会被多线程访问有关。如果它将在多个线程中访问,请使用true,以便Lazy<T>可以为您处理争用条件。如果不是,请使用false,这样Lazy<T>可以避免使用一个锁,这会给你一个非常轻微的几乎不明显的性能增益(以无争议的锁非常快)。