在C++ and the Perils of Double-Checked Lockingä¸ï¼Œä½œè€…给出了一个如何æ£ç¡®å®žçŽ°æ¨¡å¼çš„例å。
Singleton* Singleton::instance () {
Singleton* tmp = pInstance;
... // insert memory barrier (1)
if (tmp == 0) {
Lock lock;
tmp = pInstance;
if (tmp == 0) {
tmp = new Singleton;
... // insert memory barrier (2)
pInstance = tmp;
}
}
return tmp;
}
ä½†æ˜¯ï¼Œæˆ‘æ— æ³•å¼„æ¸…æ¥šï¼Œå¦‚æžœç¬¬ä¸€ä¸ªè®°å¿†éšœç¢å¿…须在Singleton* tmp = pInstance;
之åŽï¼Ÿ (编辑:è¦æ¸…楚,我明白需è¦å±éšœã€‚我ä¸æ˜Žç™½çš„是,如果必须在分é…tmp之åŽå‡ºçŽ°ï¼‰å¦‚æžœæ˜¯è¿™æ ·ï¼Œä¸ºä»€ä¹ˆï¼Ÿä»¥ä¸‹æ˜¯æ— æ•ˆçš„å—?
Singleton* Singleton::instance () {
... // insert memory barrier (1)
if (pInstance == 0) {
Lock lock;
if (pInstance == 0) {
Singleton* tmp = new Singleton;
... // insert memory barrier (2)
pInstance = tmp;
}
}
return pInstance;
}
ç”案 0 :(得分:2)
这是必ä¸å¯å°‘的。å¦åˆ™ï¼Œåœ¨å¤åˆ¶ä¹‹å‰CPUå¯èƒ½ä¼šé¢„å–if
之åŽå‘生的读å–,这将是一场ç¾éš¾ã€‚在pInstance
ä¸ä¸ºNULL并且我们没有获å–任何é”的情况下,您必须ä¿è¯åœ¨è¯»å–代ç ä¸çš„pInstance
之åŽå‘生的读å–ä¸ä¼šé‡æ–°æŽ’åºåˆ°é˜…读pInstance
。
考虑:
Singleton* tmp = pInstance;
if (tmp == 0) { ... }
return tmp->foo;
如果CPU在tmp->foo
之å‰è¯»å–tmp
ä¼šæ€Žæ ·ï¼Ÿä¾‹å¦‚ï¼ŒCPUå¯ä»¥å°†å…¶ä¼˜åŒ–为:
bool loaded = false;
int return_value = 0;
if (pInstance != NULL)
{ // do the fetch early
return_value = pInstance->foo;
loaded = true;
}
Singleton* tmp = pInstance;
if (tmp == 0) { ... }
return loaded ? return_value : tmp->foo;
注æ„这是åšä»€ä¹ˆçš„?如果指针是éžNULL,则tmp->foo
的读å–现在已移至检查之å‰ã€‚这是CPUå¯èƒ½æ‰§è¡Œçš„完全åˆæ³•çš„内å˜é¢„å–优化(推测读å–)。但它对åŒé‡æ£€æŸ¥é”定的逻辑ç»å¯¹æ˜¯ç¾éš¾æ€§çš„。
在我们看到if (tmp == 0)
为éžNULL之å‰ï¼ŒpInstance
之åŽçš„代ç ä¸èƒ½é¢„å–任何内容,这一点至关é‡è¦ã€‚å› æ¤ï¼Œæ‚¨éœ€è¦ä¸€äº›ä¸œè¥¿æ¥é˜»æ¢CPUé‡æ–°ç»„织代ç 的内å˜æ“作,如上所述。记忆障ç¢å°±æ˜¯è¿™æ ·åšçš„。
ç”案 1 :(得分:1)
ä¸ºä»€ä¹ˆä½ è¿˜åœ¨è°ˆè®º2004年的论文? C ++ 11ä¿è¯é™æ€å˜é‡åªåˆå§‹åŒ–ä¸€æ¬¡ã€‚è¿™æ˜¯ä½ çš„å…¨é¢å·¥ä½œï¼Œ100ï¼…æ£ç¡®çš„å•èº«äººå£«ï¼ˆå½“然,这是一个å模å¼çš„å•èº«äººå£«ï¼‰ï¼š
static TheTon& TheTon::instance() {
static TheTon ton;
return ton;
}