C++: Static variables in multithreaded program C++: Static variables in multithreaded program multithreading multithreading

C++: Static variables in multithreaded program


Initialization is not thread-safe. Two threads can enter the function and both may initialize the function-scope static variable. That's not good. There's no telling what the result might be.

In C++0x, initialization of function-scope static variables will be thread-safe; the first thread to call the function will initialize the variable and any other threads calling that function will need to block until that initialization is complete.

I don't think there are currently any compiler + standard library pairs that fully implement the C++0x concurrency memory model and the thread support and atomics libraries.


To pick an illustrative example at random, take an interface like asctime in the C library. The prototype looks like this:

 char * asctime(const struct tm *timeptr);

This implicitly must have some global buffer to store the characters in the char* returned. The most common and simple way to accomplish this would be something like:

 char * asctime(const struct tm *timeptr) {    static char buf[MAX_SIZE];    /* TODO: convert timeptr into string */    return buf; }

This is totally broken in a multi-threaded environment, because buf will be at the same address for each call to asctime(). If two threads call asctime() at the same time, they run the risk of overwriting each other's results. Implicit in the contract of asctime() is that the characters of the string will stick around until the next call to asctime(), and concurrent calls breaks this.

There are some language extensions that work around this particular problem in this particular example via thread-local storage (__thread,__declspec(thread)). I believe this idea made it into C++0x as the thread_local keyword.

Even so I would argue it's a bad design decision to use it this way, for similar reasons as for why it's bad to use global variables. Among other things, it may be thought of as a cleaner interface for the caller to maintain and provide this kind of state, rather than the callee. These are subjective arguments, however.


A static variable usually means multiple invocations of your function would share a state and thus interfere with one another.

Normally you want your functions to be self contained; have local copies of everything they work on and share nothing with the outside world bar parameters and return values. (Which, if you think a certain way, aren't a part of the function anyway.)

Consider:

int add(int x, int y);

definitely thread-safe, local copies of x and y.

void print(const char *text, Printer *printer);

dangerous, someone outside might be doing something with the same printer, e.g. calling another print() on it.

void print(const char *text);

definitely non-thread-safe, two parallel invocations are guaranteed to use the same printer.

Of course, there are ways to secure access to shared resources (search keyword: mutex); this is just how your gut feeling should be.

Unsynchronized parallel writes to a variable are also non-thread-safe most of the time, as are a read and write. (search keywords: synchronization, synchronization primitives [of which mutex is but one], also atomicity/atomic operation for when parallel access is safe.)