Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are pre-main global initializers guaranteed to run single-threaded?

For example, the node::node() constructor in the following snippet accesses the globals node::count and ::tail without any multithread guards. Does the C++ standard guarantee that the output would always be a permutation of 0 1 2 (regardless of the order)?

#include <stdio.h>

struct node *tail;

struct node
{
    static int count;

    int index;
    node *prev;

    node()
    {   index = count++; prev = tail; tail = this; }
};

int node::count;

node one, two[2];

int main(int argc, char *argv[])
{
    for(node *p = tail; p; p = p->prev)
        printf("%d\n", p->index);

    return 0;
}

I am looking for an answer based on the (applicable) standard, not for implementation or compiler specific behaviors. There are a number of related questions on SO but it's not entirely clear how they directly apply to this particular and rather basic case (Is C++ static member variable initialization thread-safe?, Is local static variable initialization thread-safe in C++11? etc).

like image 558
dxiv Avatar asked Jul 06 '16 02:07

dxiv


People also ask

Are static global variables thread safe?

Thread Safety Static variables are not thread safe. Instance variables do not require thread synchronization unless shared among threads. But, static variables are always shared by all the threads in the process. Hence, access to static variable is not thread safe.

Is Java static initializer thread safe?

Yes, Java static initializers are thread safe (use your first option). However, if you want to ensure that the code is executed exactly once you need to make sure that the class is only loaded by a single class-loader. Static initialization is performed once per class-loader.

Are static members thread safe C++?

According to following resources, in C++(Specially Visual C++) scoped static variable initialization isn't thread safe.

Are global variables initialized before main?

Global variables are generally written before main() function. In line 4, a and b are declared as two global variables of type int . The variable a will be automatically initialized to 0. You can use variables a and b inside any function.


1 Answers

Initialization of global variables is guaranteed single-threaded as long as the program doesn't itself start a thread (e.g. in a constructor of some global variable); once that happens, the implementation is then allowed to parallellize remaining initializations, to some extent.

[basic.start.init]/2 ...Variables with ordered initialization defined within a single translation unit shall be initialized in the order of their definitions in the translation unit. If a program starts a thread (30.3), the subsequent initialization of a variable is unsequenced with respect to the initialization of a variable defined in a different translation unit. Otherwise, the initialization of a variable is indeterminately sequenced with respect to the initialization of a variable defined in a different translation unit. If a program starts a thread, the subsequent unordered initialization of a variable is unsequenced with respect to every other dynamic initialization. Otherwise, the unordered initialization of a variable is indeterminately sequenced with respect to every other dynamic initialization. [ Note: This definition permits initialization of a sequence of ordered variables concurrently with another sequence. —end note ]

"Indeterminately sequenced" is the part that guarantees single-threaded execution. By definition, the notion of sequenced {before, after, indeterminately} is only meaningful within a single thread:

[intro.execution]/13 Sequenced before is a ... relation between evaluations executed by a single thread...

like image 107
Igor Tandetnik Avatar answered Nov 09 '22 01:11

Igor Tandetnik