这不是关于静态初始化和线程安全的问题。由于标准中使用的措辞,它们在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
AType
和AnotherType
中的value
和id
可以具有相同的值。
另一方面,在v
的{{1}}静态初始化期间调用value
,因此我对期望的有效性不确定 。
这就是我问的原因。我的推理是否有问题,或者上面的代码实际上并不是线程安全的?
答案 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;
}
};
请注意,避免增加后期是一种好习惯。