Is static init thread-safe with VC2010? Is static init thread-safe with VC2010? multithreading multithreading

Is static init thread-safe with VC2010?


From Visual Studio 2010's documentation on Static:

Assigning a value to a static local variable in a multithreaded application is not thread safe and we do not recommend it as a programming practice.

The second part of your question has some good existing answers.

Updated Nov 22, 2015:

Others have verified, specifically, that static initialization is not thread safe either (see comment and other answer).

User squelart on VS2015:

you may want to add that VS2015 finally gets it right: https://msdn.microsoft.com/en-au/library/hh567368.aspx#concurrencytable ("Magic statics")


The following code snippet shows "locally scoped static object initialisation" is NOT thread-safe:

#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;}

The output will be(of course thread id will be different on your machine):

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

Before the first thread returns which means the singleton's ctor is called and returned, the second thread get the un-initialized object and call it's member method(because the static object is in BSS segment, it'll be initilized to zero after loader load the executable) and get the wrong value: 0.

Turning on assembly listing by /FAsc /Fastatic.asm will get the assembly code for function getX():

01:  ?getX@@YAAAUX@@XZ PROC                 ; getX02:  03:  ; 20   : {04:  05:    00000    55       push    ebp06:    00001    8b ec        mov     ebp, esp07:  08:  ; 21   :   static X static_x(1000);09:  10:    00003    a1 00 00 00 00   mov     eax, DWORD PTR ?$S1@?1??getX@@YAAAUX@@XZ@4IA11:    00008    83 e0 01     and     eax, 112:    0000b    75 2b        jne     SHORT $LN1@getX13:    0000d    8b 0d 00 00 0014:     00       mov     ecx, DWORD PTR ?$S1@?1??getX@@YAAAUX@@XZ@4IA15:    00013    83 c9 01     or  ecx, 116:    00016    89 0d 00 00 0017:     00       mov     DWORD PTR ?$S1@?1??getX@@YAAAUX@@XZ@4IA, ecx18:    0001c    68 e8 03 00 00   push    1000           ; 000003e8H19:    00021    b9 00 00 00 00   mov     ecx, OFFSET ?static_x@?1??getX@@YAAAUX@@XZ@4U2@A20:    00026    e8 00 00 00 00   call    ??0X@@QAE@H@Z      ; X::X21:    0002b    68 00 00 00 00   push    OFFSET ??__Fstatic_x@?1??getX@@YAAAUX@@XZ@YAXXZ ; `getX'::`2'::`dynamic atexit destructor for 'static_x''22:    00030    e8 00 00 00 00   call    _atexit23:    00035    83 c4 04     add     esp, 424:  $LN1@getX:25:  26:  ; 22   :   return static_x;27:  28:    00038    b8 00 00 00 00   mov     eax, OFFSET ?static_x@?1??getX@@YAAAUX@@XZ@4U2@A29:  30:  ; 23   : }

At line 10 the cryptic symbol [?$S1@?1??getX@@YAAAUX@@XZ@4IA] is the global indicator(also in BSS) which flags whether the singleton is ctored or not, it will be flaged as true by line 14-17, just before calling into the ctor, that's the problem, this also explains why the second thread immediately got the un-initialized singleton object and happily call it's member function. There's no thread-safety related code inserted by the compiler.