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

时间:2017-10-17 12:35:30

标签: 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++;
    }
};

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

§6.7 [stmt.dcl] p4
  

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

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

static size_t index{ NextIndex() };

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

1 个答案:

答案 0 :(得分: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;
}

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

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