我想知道下面代码中对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
原子化,那还有其他方法可以使线程安全吗?
答案 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>()
)会产生数据竞争。