[英]Name for this pattern? (Answer: lazy initialization with double-checked locking)
考慮以下代碼:
public class Foo
{
private static object _lock = new object();
public void NameDoesNotMatter()
{
if( SomeDataDoesNotExist() )
{
lock(_lock)
{
if( SomeDataDoesNotExist() )
{
CreateSomeData();
}
else
{
// someone else also noticed the lack of data. We
// both contended for the lock. The other guy won
// and created the data, so we no longer need to.
// But once he got out of the lock, we got in.
// There's nothing left to do.
}
}
}
}
private bool SomeDataDoesNotExist()
{
// Note - this method must be thread-safe.
throw new NotImplementedException();
}
private bool CreateSomeData()
{
// Note - This shouldn't need to be thread-safe
throw new NotImplementedException();
}
}
首先,我需要陳述一些假設:
一個很好的理由是我不能在應用程序啟動后立即執行此操作。 也許數據還不可用,等等。
Foo可以從兩個或更多線程中實例化並同時使用。 我希望其中之一最終創建一些數據(但不能同時創建兩個數據),然后允許兩者訪問同一數據(忽略訪問數據的線程安全性)
SomeDataDoesNotExist()的代價並不高。
現在,這不必一定局限於某些數據創建情況,但這是我能想到的一個例子。
我特別希望將其識別為模式的部分是check-> lock-> check。 我不得不在某些情況下向開發人員解釋這種模式,這些開發人員乍一看並沒有理解算法,但隨后可能會欣賞它。
無論如何,其他人也必須做類似的事情。 這是標准模式嗎? 它叫什么?
盡管我可以看到您可能會認為這看起來像是雙重檢查鎖定,但實際上看起來是危險的,並且錯誤的雙重檢查鎖定 。 如果沒有對SomeDataDoesNotExist和CreateSomeData的實際實現進行批評,我們就無法保證該東西實際上在每個處理器上都是線程安全的。
有關分析雙重檢查鎖定可能出錯的示例,請查看此錯誤的雙重檢查鎖定版本:
我的建議:在沒有令人信服的理由和內存模型專家的代碼審查的情況下,不要使用任何低鎖技術; 您可能會弄錯。 大多數人都這樣做。
特別是,不要使用雙重檢查鎖定,除非您可以確切描述處理器可以代表您進行哪些內存訪問重新排序,並提供令人信服的論點,即鑒於任何可能的內存訪問重新排序 ,您的解決方案都是正確的。 一旦您稍微偏離了已知的正確實現,就需要從頭開始進行分析。 您不能僅僅因為雙重檢查鎖定的一種實現是正確的就假定它們都是正確的。 幾乎沒有一個是正確的。
帶有雙重檢查鎖定的延遲初始化?
我特別希望將其識別為模式的部分是check-> lock-> check。
這就是所謂的雙重檢查鎖定 。
請注意,在較舊的Java版本(Java 5之前的版本)中,由於Java的內存模型是如何定義的,因此這是不安全的。 在Java 5和更高版本中,對Java內存模型的規范進行了更改,因此現在是安全的。
想到的唯一的名稱是“故障”。 此名稱在iOS Core-Data框架中使用,效果相似。
基本上,您的NameDoesNotMatter方法是一個Fault ,每當有人調用它時,就會導致該對象被填充或初始化。
有關如何使用此設計模式的更多詳細信息,請參見http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdFaultingUniquing.html 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.