C++ 线程安全和静态变量/成员函数
这不是关于静态初始化和线程安全的问题。由于标准中使用的措辞,自C++11以来,它们一起得到保证。C++ 线程安全和静态变量/成员函数,c++,thread-safety,c++14,static-initialization,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 in
到目前为止,一切顺利。请考虑下面的类:
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;
}
};
结构{
静态int id()无异常{
静态int v=0;
返回v++;
}
模板
静态int值()无异常{
静态常量int v=id();
返回v;
}
};
在这种情况下,在不同线程上对S::value()
进行的两个并发调用是安全的(如果我错了,请纠正我)
像S::value()
和S::value()
这样的两个并发调用也安全吗
就我所见,value
本身并不是一个问题,因为不同的专门化。但是,在调用id
时,保证第一行(静态初始化)是线程安全的,但这并不适用于紧接其后的行。因此,
v
对于value
中的attype
和AnotherType
可以具有相同的值另一方面,
id
在value
中的v
的静态初始化过程中被调用,因此我不确定我的期望是否有效。这就是我问的原因。我的推理是否有问题,或者上面的代码实际上不是线程安全的?没有。您必须进行同步,但在您的情况下,它非常简单:
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;
}
};
结构{
静态int id()无异常{
静态std::原子v{0};
return++v;
}
模板
静态int值()无异常{
静态常量int v=id();
返回v;
}
};
注意,避免后增量是一种很好的做法。避免后增量的结果是,在您的情况下,永远不会返回0。实际上,这不是我能接受的,而且
v
是size\u t
。因此,不幸的是,我无法避免后期初始化。您可以将您的问题与fetch\u add
结合起来,以维护后期增量行为。