2012-03-26 40 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>可以避免使用一個鎖,這會給你一個非常輕微的幾乎不明顯的性能增益(以無爭議的鎖非常快)。