2012-05-14 17 views
10

Ich habe rund um SO und MSDN für eine Antwort auf diese Frage gesucht, aber kann nicht scheinen, eine klare und endgültige Antwort zu finden ...Ist statische Initialisierung mit VC2010 Thread-sicher?

Ich weiß, dass es in der C++ 11 Standard und das aktuelle ist Die GCC-Version verhält sich so, aber garantiert VC2010 aktuell die Thread-Sicherheit einer lokalen statischen Variableninitialisierung?

d. H .: Ist das Thread-Safe mit VC2010?

static S& getInstance() 
    { 
     static S instance; 
     return instance; 
    } 

... Und wenn nicht, was ist die aktuelle beste Praxis eine Thread-sichere Implementierung Singleton in C++ mit VC2010 zu bekommen?

EDIT: Wie Chris Betti Antwort darauf ausgeführt, implementiert VC2010 Thread-Sicherheit der lokalen statischen Variable init nicht.

+0

Siehe http: // stackoverflow.com/questions/164496/how-can-ich-create-a-thread-safe-singleton-muster-in-windows – MerickOWA

+0

@MerickOWA: Dies stammt aus dem Jahr 08 und bietet keine klare und weltweit akzeptierte Antwort. Außerdem deckt es VC2010 nicht ab (aufgrund des Themenalters). –

+0

@ IC3M4N VS2010 wurde implementiert, bevor C++ 11 herauskam. Wenn es keine threadsichere Konstruktion von statischen lokalen Variablen implementiert, dann bleibt die Verwendung von Techniken übrig, die es schon seit vielen Jahren gibt. Ich sehe nichts, was nicht auf VS2010 – MerickOWA

Antwort

11

von Visual Studio 2010 ist documentation on Static:

Wert auf eine statische lokale Variable in einer Multithread-Anwendung Gewinde ist nicht sicher zuordnen und wir es nicht als Programmier Praxis empfehlen.

Der zweite Teil Ihrer Frage hat some good existing answers.

Aktualisiert 22. November 2015:

Andere überprüft haben, insbesondere, dass die statische Initialisierung nicht Thread-sicher entweder (Antwort siehe Kommentar und andere).

Benutzer squelart auf VS2015:

Sie können hinzufügen, dass VS2015 bekommt endlich es richtig: https://msdn.microsoft.com/en-au/library/hh567368.aspx#concurrencytable ("Magic Statik")

+0

Seit C++ 11 ist es threadsicher. – Jagannath

+6

Vereinbart, dass C++ 11 Thread-sicher erfordert, aber das bedeutet nicht, dass VS2010 diese Anforderung implementiert. Laut ihrer Dokumentation ist die Anforderung nicht erfüllt. –

+0

@ Jagannath Wie gesagt, ich weiß das. Ich fragte nach VC2010 Implementierung dieser besonderen C++ 11-Funktion. –

7

Der folgende Codeausschnitt zeigt „lokal scoped statisches Objekt Initialisierung“ist nicht Thread-sicher:

#include <windows.h> 
#include <stdio.h> 
#include <process.h> 
struct X { 
    ~X() { puts("~X()"); } 
    int i_ ; 
    void print(void) { 
     printf("thread id=%u, i = %d\n", GetCurrentThreadId(), i_); 
    } 
    X(int i) { 
     puts("begin to sleep 10 seconds"); 
     Sleep(1000 * 10); 
     i_ = i; 
     printf("X(int) i = %d\n", i_); 
     puts("end"); 
    } 
}; 

X & getX() 
{ 
    static X static_x(1000); 
    return static_x; 
} 

void thread_proc(void *) 
{ 
    X & x = getX(); 
    x.print(); 
} 

int main(int argc, char *argv[]) 
{ 
    HANDLE all_threads[2] = {}; 
    all_threads[0] = HANDLE(_beginthread(thread_proc, 0, 0)); 
    printf("First thread Id: %u\n", GetThreadId(all_threads[0])); 
    Sleep(1000); 
    all_threads[1] = HANDLE(_beginthread(thread_proc, 0, 0)); 
    printf("Second thread Id: %u\n", GetThreadId(all_threads[1])); 
    WaitForMultipleObjects(_countof(all_threads), all_threads, TRUE, 1000 * 20); 
    puts("main exit"); 
    return 0; 
} 

der Ausgang (natürlich Thread-ID wird auf Ihrem Computer unterschiedlich sein) sein wird:

First thread Id: 20104 
begin to sleep 10 seconds 
Second thread Id: 20248 
thread id=20248, i = 0 
X(int) i = 4247392 
end 
thread id=20104, i = 1000 
main exit 
~X() 

vor dem ersten Thread kehren die die Singletons Ctor Mittel genannt wird und zurückgeführt, wobei der zweite Thread das nicht initialisierten Objekt erhalten, und nennt es Mitglied Methode (da das statische Objekt in BSS-Segment ist, wird es sein, initilized auf Null nach Lader der ausführbaren Datei laden) und den falschen Wert erhalten: 0.

Montag durch die Auflistung Ein-/fasc /Fastatic.asm den Assembler-Code für die Funktion getX() erhalten:

01: [email protected]@[email protected]@XZ PROC     ; getX 
02: 
03: ; 20 : { 
04: 
05: 00000 55  push ebp 
06: 00001 8b ec  mov  ebp, esp 
07: 
08: ; 21 : static X static_x(1000); 
09: 
10: 00003 a1 00 00 00 00 mov  eax, DWORD PTR [email protected][email protected]@[email protected]@[email protected] 
11: 00008 83 e0 01  and  eax, 1 
12: 0000b 75 2b  jne  SHORT [email protected] 
13: 0000d 8b 0d 00 00 00 
14:  00  mov  ecx, DWORD PTR [email protected][email protected]@[email protected]@[email protected] 
15: 00013 83 c9 01  or ecx, 1 
16: 00016 89 0d 00 00 00 
17:  00  mov  DWORD PTR [email protected][email protected]@[email protected]@[email protected], ecx 
18: 0001c 68 e8 03 00 00 push 1000   ; 000003e8H 
19: 00021 b9 00 00 00 00 mov  ecx, OFFSET [email protected][email protected]@[email protected]@[email protected]@A 
20: 00026 e8 00 00 00 00 call [email protected]@[email protected]@Z  ; X::X 
21: 0002b 68 00 00 00 00 push OFFSET [email protected][email protected]@[email protected]@[email protected] ; `getX'::`2'::`dynamic atexit destructor for 'static_x'' 
22: 00030 e8 00 00 00 00 call _atexit 
23: 00035 83 c4 04  add  esp, 4 
24: [email protected]: 
25: 
26: ; 22 : return static_x; 
27: 
28: 00038 b8 00 00 00 00 mov  eax, OFFSET [email protected][email protected]@[email protected]@[email protected]@A 
29: 
30: ; 23 : } 

In Zeile 10 wird das kryptische Symbol [? $ S1 @? 1 ?? getX @@ YAAAUX @@ XZ @ 4IA] ist der globale Indikator (auch in BSS), der anzeigt, ob der Singleton corted ist oder nicht, er wird als wahr gewertet durch Zeile 14-17, kurz bevor er in den ctor ruft, das ist das Problem, das auch erklärt, warum der zweite Thread sofort das nicht initialisierte Singleton-Objekt erhalten hat und es glücklich als Member-Funktion bezeichnet. Es gibt keinen threadsicherheitsbezogenen Code, der vom Compiler eingefügt wurde.

+1

Heute habe ich das mit VS2013 überprüft, (leider) ist das Ergebnis gleich. – zhaorufei

Verwandte Themen