线程安全性和静态变量/成员函数

时间:2018-02-27 16:20:06

标签: c++ thread-safety c++14 static-initialization

这不是关于静态初始化和线程安全的问题。由于标准中使用的措辞,它们在C ++ 11之后得到了保证 到现在为止还挺好。请考虑以下类:

struct S {
    static int id() noexcept {
        static int v = 0;
        return v++;
    }

    template<typename>
    static int value() noexcept {
        static const int v = id();
        return v;
    }
};

在这种情况下,在不同线程上对S::value<MyType>()进行两次并发调用是安全的(如果我错了,请纠正我。)

两个并发呼叫如S::value<AType>()S::value<AnotherType>()是否安全?

据我所知,由于不同的专业化,value本身并不是一个问题。但是,当涉及调用id时,第一行(静态初始化)保证是线程安全的,但同样不会立即应用于该行。
因此,v ATypeAnotherType中的valueid可以具有相同的值。
另一方面,在v的{​​{1}}静态初始化期间调用value,因此我对期望的有效性不确定
这就是我问的原因。我的推理是否有问题,或者上面的代码实际上并不是线程安全的?

1 个答案:

答案 0 :(得分:2)

没有。你必须做同步,但在你的情况下它很简单:

struct S {
    static int id() noexcept {
        static std::atomic<int> v { 0 };
        return ++v;
    }

    template<typename>
    static int value() noexcept {
        static const int v = id();
        return v;
    }
};

请注意,避免增加后期是一种好习惯。