繁体   English   中英

WaitForSingleObject是否可用作内存屏障?

[英]Does WaitForSingleObject Serve as a Memory Barrier?

昨天关于双重检查锁定的一个问题引发了一连串的想法,让我不确定一个简单的情况。 在下面的代码中,是否可以点击“不再同步”的printf 在这个简单的例子中,值可能在同一个缓存行上,所以我认为它不太可能(假设开始时可能性> 0%)。

如果答案是“不,这是不可能的。”,那么我的后续问题是,相当可预见的:为什么不呢? 直到昨天我的想法纠结并缠绕在多线程轴上,我认为代码是安全的。 但是现在我想知道是什么阻止了从缓存中读取一个变量papb的过时。 如果pa, pb指向简单的全局整数变量而不是malloc内存pa, pb那会不会有问题? WaitForSingleObject调用是否提供内存屏障? 或者指针是否应声明为volatile? 这么多问题,句子很少。

更新 :我最终找到的信息明确指出,信号同步对象的函数确实使用了内存屏障 应该是显而易见的,但我找不到明确的答案。 所以我可以再次欺骗自己相信我理解这一切。

int i1 = 0;
int i2 = 0;
int reads = 0;
int done = 0;
int *pa = NULL;
int *pb = NULL;
HANDLE hSync = NULL;

DWORD WriteThread( LPVOID pvParam )
{
   while( !done )
      {
      WaitForSingleObject( hSync, INFINITE );
      (*pa)++;
      (*pb)++;
      ReleaseSemaphore( hSync, 1, NULL );
      }
   return 0;
}

DWORD ReadThread( LPVOID pvParam )
{
   while( !done )
      {
      WaitForSingleObject( hSync, INFINITE );
      if ( *pa != *pb )
         {
         printf( "No longer in sync: %d, %d\n", *pa, *pb );
         exit( 1 );
         }
      ReleaseSemaphore( hSync, 1, NULL );
      reads++;
      }
   return 0;
}

int main( int argc, char* argv[] )
{
   DWORD dwID;

   // malloc'd memory
   pa = (int*)malloc( sizeof( int ));
   pb = (int*)malloc( sizeof( int ));

   // Is a simple global variable different?
   //pa = &i1;
   //pb = &i2;

   *pa = 0;
   *pb = 0;

   hSync = CreateSemaphore( NULL, 1, 1, NULL );
   CreateThread( NULL, 0, WriteThread, NULL, 0, &dwID );
   CreateThread( NULL, 0, ReadThread, NULL, 0, &dwID );

   while ( *pa < 1000000 )
      Sleep( 1 );
   done = 1;

   return 0;
}

内存所在的位置并不重要,如果它都是关于缓存一致性的,那么声明变量volatile将无法解决它。 易失性的语义对于线程安全既不必要也不充分; 不要用它!

在C / C ++级别,pa和pb可以缓存在寄存器中,但在任何函数调用之后它们将被视为过时。 在CPU级别,所有等待函数都使用障碍来确保一切按预期工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM