在图书馆的某个地方,我有一个看起来像 -
的功能<h1> <br> <hr> <p>
现在您可以阅读inline int getIword()
{
static int i = std::ios_base::xalloc();
return i;
}
来电here,但我想从提到的链接强调这一行 -
此功能是线程安全的;多个线程的并发访问不会导致数据竞争。 (自C ++ 14起)
它说“自C ++ 14以来”,但我也需要C ++ 11支持。由于函数调用实际上正在初始化std::ios_base::xalloc()
方法的静态局部变量,并且我们知道C ++ 11代码的local static variable initialization is thread safe,因此可以安全地假设此代码是 -
安全,如果只有后续的读取调用功能,例如。 getIword()
。
安全吗?如果代码如下所示:
...
auto something = getIword()
...
如果在后面的示例中它不安全,我应该在哪里放置lock_guards以使其对C ++ 11安全?大约operator<<(std::ostream &os, T const value)
{
if (value == ...) {
os.iword(getIword()) = 1;
} else if (value == ...) {
os.iword(getIword()) = 0;
}
return os;
}
或整个方法或正在进行通话的地方?
答案 0 :(得分:3)
静态局部变量初始化是线程安全的,因为如果多个线程调用该函数,那么其中只有一个实际上会初始化该变量。它不保护您初始化的东西。这意味着在这种情况下,如果你有两个不同的线程,一个调用getIword
而另一个调用另一个函数同时调用std::ios_base::xalloc()
,那么这两个调用将不会同步,你将有一个数据竞争,而这又是未定义的行为。
答案 1 :(得分:1)
在我的电脑上,我可以看到std::ios_base::xalloc()
的实现是:
static int __CLRCALL_OR_CDECL xalloc()
{ // allocate new iword/pword index
_BEGIN_LOCK(_LOCK_STREAM) // lock thread to ensure atomicity
return (_Index++);
_END_LOCK()
}
所以基本上它只是做一个增量值,没有线程安全保证你会在竞争条件下从std::ios_base::xalloc()
获得一些重复值。
我将采取的解决方案是使用xalloc()
编写自己的std::atomic
。
int xalloc()
{
static std::atomic_int i;
return i++;
}
使用锁定将std::ios_base::xalloc()
包装到新方法。