我使用Visual Studio 2015 Preview构建下面的代码(但我在Visual Studio 2013中遇到了类似的问题,因此它并不是特定于2015年),然后运行程序在英特尔Inspector XE 2013 Update 9(build 328075)下。英特尔检查器在代码中报告了几个数据争用,围绕对shared_ptr及其原子内容的访问。 Intel Inspector is known to report false positive races,我只想确认确实是这种情况,并了解这是Inspector或Microsoft STL实现中的问题......
这是代码,有2个线程,它们同时并原子地修改指向原子int的shared_ptr,并且其中一个线程也打印点(这样你就可以观察控制台上打印的活动):
#include <memory>
#include <atomic>
#include <thread>
#include <iostream>
using namespace std;
int main()
{
shared_ptr<atomic<int>> a;
atomic_store(&a, make_shared<atomic<int>>(42));
thread t1([&]
{
for (int i = 0; i < 1000000; i++)
{
auto ptr_copy = atomic_load(&a);
if (*ptr_copy == 42)
*ptr_copy = 0;
}
});
thread t2([&]
{
for (int i = 0; i < 1000000; i++)
{
auto ptr_copy = atomic_load(&a);
if (*ptr_copy == 0)
{
atomic_store(&a, make_shared<atomic<int>>(42));
cout << ".";
}
}
});
t1.join();
t2.join();
}
这是报道的数据竞赛之一,摘录:
P1: Error: Data race
Error X22: Write: Function operator()
Code snippet:
28 if (*ptr_copy == 0)
29 {
>30 atomic_store(&a, make_shared<atomic<int>>(42));
31 cout << ".";
32 }
Error X23: Read: Function atomic_load_explicit<struct std::atomic<int> >
Code snippet:
1919 { // load *_Ptr atomically
1920 _Shared_ptr_spin_lock _Lock;
>1921 shared_ptr<_Ty> _Result = *_Ptr;
1922 return (_Result);
1923 }
Stack (1 of 1 instance(s))
>AtomicSharedPtrRace1.exe!atomic_load_explicit<struct std::atomic<int> > - c:\program files (x86)\microsoft visual studio 14.0\vc\include\memory:1921
AtomicSharedPtrRace1.exe!atomic_load<struct std::atomic<int> > - c:\program files (x86)\microsoft visual studio 14.0\vc\include\memory:1928
AtomicSharedPtrRace1.exe!operator() - atomicsharedptrrace1.cpp:17
我认为Intel Inspector无法将shared_ptr内部自旋锁识别为同步机制......
如果是这样,是否符合atomic_store / atomic_load的MS STL实现标准?它完全忽略了内存顺序参数,似乎使用全局自旋锁,是否意味着它总是强制执行内存操作的顺序一致性并作为编译器屏障(即使我放松了memory_order)?
template <class _Ty> inline
shared_ptr<_Ty> atomic_load_explicit(const shared_ptr<_Ty> *_Ptr,
memory_order)
{ // load *_Ptr atomically
_Shared_ptr_spin_lock _Lock;
shared_ptr<_Ty> _Result = *_Ptr;
return (_Result);
}
这是Microsoft的实施问题,英特尔检查员无法识别自旋锁,还是英特尔检查器出现问题?我想找到一些解决方法,我怀疑Inspector在我们的代码中报告的许多其他数据竞争可能是误报,因为它们位于我们使用atomic_load和atomic_store的地方。我知道atomic_load and atomic_store will likely be deprecated in future,但是我想在那之前以某种方式理清那些误报......