静态变量初始化的线程安全性

NuP*_*adi 13 c++ multithreading c++11

我想知道Get()下面代码中对不同参数类型的2次调用是否是线程安全的:

struct MethodTypeIndex
{
    template <typename T>
    static size_t Get(T)
    {
        static size_t index = NextIndex();
        return index;
    }
private:
    static size_t NextIndex()
    {
        static size_t nextIndex = 0;
        return nextIndex++;
    }
};
Run Code Online (Sandbox Code Playgroud)

一方面,NextIndex()在初始化期间调用index并根据标准:

§6.7 [stmt.dcl] p4
Run Code Online (Sandbox Code Playgroud)

如果控制在初始化变量时同时进入声明,则并发执行应等待初始化完成.

另一方面,我不知道是否将调用NextIndex()视为初始化的一部分index.如果没有,支撑初始化会有所不同吗?

static size_t index{ NextIndex() };
Run Code Online (Sandbox Code Playgroud)

或者,如果我不想制作nextIndex原子线,还有其他方法可以使线程安全 吗?

Pet*_*ker 17

假装你有两个不同的功能:

static size_t get_int() {
    static size_t index = NextIndex();
    return index;
}
static size_t get_long() {
    static size_t index = NextIndex();
    return index;
}
Run Code Online (Sandbox Code Playgroud)

您是否有任何疑问,从单独的线程调用这两个函数是不是线程安全的?显然,在调用中存在数据竞争NextIndex.

通过实例化模板函数来创建这些函数并不能消除数据竞争.模板不是代码 ; 它们是用于创建代码的模式.从两个不同的线程调用模板函数的两个不同实例(例如,和)会产生数据争用.Get<int>()Get<long>()