[现代Intel上的C ++ 11:我疯了还是非原子对齐的64位加载/存储实际上是原子的?

问题描述 投票:2回答:1

我能否将一项关键任务应用程序基于此测试的结果,即100个线程读取一个主线程设置的十亿次指针永远不会流泪?

除了撕扯还有其他潜在的问题吗?

这里是使用g++ -g tear.cxx -o tear -pthread编译的独立演示。

#include <atomic>
#include <thread>
#include <vector>

using namespace std;

void* pvTearTest;
atomic<int> iTears( 0 );

void TearTest( void ) {

  while (1) {
      void* pv = (void*) pvTearTest;

      intptr_t i = (intptr_t) pv;

      if ( ( i >> 32 ) != ( i & 0xFFFFFFFF ) ) {
          printf( "tear: pv = %p\n", pv );
          iTears++;
      }
      if ( ( i >> 32 ) == 999999999 )
          break;

  }
}



int main( int argc, char** argv ) {

  printf( "\n\nTEAR TEST: are normal pointer read/writes atomic?\n" );

  vector<thread> athr;

  // Create lots of threads and have them do the test simultaneously.

  for ( int i = 0; i < 100; i++ )
      athr.emplace_back( TearTest );

  for ( int i = 0; i < 1000000000; i++ )
      pvTearTest = (void*) (intptr_t)
                   ( ( i % (1L<<32) ) * 0x100000001 );

  for ( auto& thr: athr )
      thr.join();

  if ( iTears )
      printf( "%d tears\n", iTears.load() );
  else
      printf( "\n\nTEAR TEST: SUCCESS, no tears\n" );
}

实际的应用程序是malloc()的数组,有时是realloc()的数组(大小为2的幂;重新分配存储量的两倍),许多子线程绝对会在关键任务中发挥作用,但在高性能方面,关键方式。

线程有时会需要向该数组添加一个新条目,这将通过将下一个数组条目设置为指向某个对象,然后增加atomic<int> iCount来实现。最后,它将数据添加到某些数据结构中,这将导致其他线程尝试取消对该单元格的引用。

这一切似乎都很好(除非我确定肯定会在进行非原子更新之前发生计数的增加,否则我不是很肯定)... 例外一件事:realloc()通常会更改地址数组,然后further释放旧的数组,指向该数组的指针对其他线程仍然可见。

[确定,所以我不是realloc(),而是我malloc()一个新的数组,手动复制内容,将指针设置为该数组。我会释放旧的数组,但是我意识到其他线程可能仍在访问它:它们读取数组的基数;我释放了基地;第三个线程分配它在那里写其他内容;然后,第一个线程将索引的偏移量添加到基数,并期望一个有效的指针。我很乐意泄漏这些。 (鉴于增长一倍,所有合并的旧数组的大小与当前数组的大小大致相同,因此每个项目的开销只是额外的16个字节,而且很快便不再引用它的内存。)

所以,这就是问题的症结所在:一旦分配了更大的数组,就可以完全安全地使用非原子写入来写入基地址吗?还是尽管进行了十亿次访问测试,但实际上是否必须使它成为atomic <>,从而减慢所有辅助线程的读取速度?

((因为这肯定是环境相关的,所以我们所说的是2012年或以后的Intel,g ++ 4到9,以及2012年或以后的Red Hat。)

我能否将一项关键任务应用程序基于此测试的结果,即100个线程读取一个主线程设置的十亿次指针永远不会流泪?做其他任何潜在的问题...

c++11 c++14 c++17 stdthread stdatomic
1个回答
3
投票

是的,在x86上对齐的负载是原子的,BUT

© www.soinside.com 2019 - 2024. All rights reserved.