多个线程竞相将相同的数据设置为相同的值
Several Threads racing to set the same data to the same value
我有一种情况,我不得不使用黑盒包装器进行多线程处理(我怀疑它位于 TBB 线程池之上)。
我有一个值只能由具有昂贵构造函数的对象获取,并且每个线程都需要它的一个本地实例,这没问题。
该对象将产生一个保证跨线程始终相同的值(所有构造函数从主循环采用相同的 const 形成参数)。
每个线程还可以访问该参数的共享结构并保存一些结果。
线程所需的相关值(unsigned int 形式的迭代范围)稍后在主循环中使用,因此如果可以的话我宁愿不创建上述对象的另一个昂贵实例只是为了再次获得相同的价值。
我的问题是,在使用 VC11 的 Windows 和使用 GCC 4.8.2 的 Linux 上,在 x86-64 上,正在将相同的值写入相同的内存位置(结构中的 int线程有一个指针指向)来自多个线程的良性竞争?这是一场我可以让其发生而不用昂贵的锁来保护价值的比赛吗?从粗略的测试来看,情况似乎是这样,但我不完全确定该操作在幕后是否是原子的和安全的,或者是否存在可能在压力下出现的损坏。
数据竞争是否 "benign" 取决于编译器和运行时平台。编译器假定程序是无竞争的,并且竞争条件导致的行为是未定义的。使用原子操作不会产生太多开销,在这种情况下推荐使用。
一些边缘案例和关于可能出错的很好的例子可以在这里找到:
https://software.intel.com/en-us/blogs/2013/01/06/benign-data-races-what-could-possibly-go-wrong
ThreadSanitizer 开发人员 Dmitry Vyukov 在他的 post 中写道 "So, if a data race involves non-atomic writes, it always can go wrong"。
我有一种情况,我不得不使用黑盒包装器进行多线程处理(我怀疑它位于 TBB 线程池之上)。
我有一个值只能由具有昂贵构造函数的对象获取,并且每个线程都需要它的一个本地实例,这没问题。 该对象将产生一个保证跨线程始终相同的值(所有构造函数从主循环采用相同的 const 形成参数)。 每个线程还可以访问该参数的共享结构并保存一些结果。
线程所需的相关值(unsigned int 形式的迭代范围)稍后在主循环中使用,因此如果可以的话我宁愿不创建上述对象的另一个昂贵实例只是为了再次获得相同的价值。
我的问题是,在使用 VC11 的 Windows 和使用 GCC 4.8.2 的 Linux 上,在 x86-64 上,正在将相同的值写入相同的内存位置(结构中的 int线程有一个指针指向)来自多个线程的良性竞争?这是一场我可以让其发生而不用昂贵的锁来保护价值的比赛吗?从粗略的测试来看,情况似乎是这样,但我不完全确定该操作在幕后是否是原子的和安全的,或者是否存在可能在压力下出现的损坏。
数据竞争是否 "benign" 取决于编译器和运行时平台。编译器假定程序是无竞争的,并且竞争条件导致的行为是未定义的。使用原子操作不会产生太多开销,在这种情况下推荐使用。
一些边缘案例和关于可能出错的很好的例子可以在这里找到: https://software.intel.com/en-us/blogs/2013/01/06/benign-data-races-what-could-possibly-go-wrong
ThreadSanitizer 开发人员 Dmitry Vyukov 在他的 post 中写道 "So, if a data race involves non-atomic writes, it always can go wrong"。