是否WaitForSingleObject的充当内存屏障? [英] Does WaitForSingleObject Serve as a Memory Barrier?

查看:90
本文介绍了是否WaitForSingleObject的充当内存屏障?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

约一倍检查锁定一个问题,昨天开始的那给我留下不确定的简单情况的想法链。在下面的code,有没有可能打的的printf 不再同步?在这个简单的例子,值很可能会在同一高速缓存行,所以我认为这将是不太可能(假设的可能性> 0%开始)。

如果回答是,不,这是不可能的。然后我的后续问题是,相当predictably:为什么不呢?直到我得到了我的思绪纠结昨天围绕多线程阿克塞尔包裹着,我假定code将是安全的。但现在我想知道什么prevents从缓存中读取过时的变量之一每年 PB 。并且将它的问题,如果 PA,PB 指出,简单的全局整型变量,而不是malloc分配的内存?是否WaitForSingleObject的调用提供了一个内存屏障?还是应该指针声明波动?这么多问题,所以几句话。

更新:我终于位置的信息,它明确说,该信号的同步对象的功能确实使用的内存屏障的。它应该是显而易见的,但我无法找到一个明确的答案。这样我就可以自己再次欺骗相信我明白这一切。

  INT I1 = 0;
INT I2 = 0;
INT读取= 0;
做了诠释= 0;
为int * PA = NULL;
INT * PB = NULL;
HANDLE HSYNC = NULL;DWORD WriteThread(LPVOID pvParam)
{
   而(!完成)
      {
      WaitForSingleObject的(HSYNC,INFINITE);
      (* PA)++;
      (* PB)++;
      ReleaseSemaphore(HSYNC,1,NULL);
      }
   返回0;
}DWORD ReadThread(LPVOID pvParam)
{
   而(!完成)
      {
      WaitForSingleObject的(HSYNC,INFINITE);
      如果(*啪!= * PB)
         {
         的printf(不再同步数:%d,%d个\\ N,* PA,* PB);
         出口(1);
         }
      ReleaseSemaphore(HSYNC,1,NULL);
      读++;
      }
   返回0;
}INT主(INT ARGC,CHAR *的argv [])
{
   DWORD dwID;   // malloc分配内存
   PA =(INT *)malloc的(的sizeof(INT));
   PB =(INT *)malloc的(的sizeof(INT));   //是一个简单的全局变量有什么不同?
   // 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);   而(* PA< 1000000)
      睡眠(1);
   做= 1;   返回0;
}


解决方案

不要紧,那里的记忆所在,如果它是所有关于高速缓存一致性,则宣告变量波动会做什么来解决它。挥发性的语义是既无必要,也足以线程安全;不要使用它!

在C / C ++级,PA和PB可以在寄存器中缓存,但它们将被视为任何函数调用后失效。在CPU级别,所有的等待函数使用的障碍,以确保一切正常。

A question yesterday about doubled-checked locking started a chain of thoughts that left me unsure about a simple situation. In the following code, is it possible to hit the printf of "No longer in sync"? In this simple example, the values would likely be on the same cache line, so I think it would be less likely (assuming the possibility is > 0% to begin with).

If the answer is, "No, it is not possible.", then my follow-up question is, rather predictably: why not? Until I got my thoughts tangled and wrapped around the multi-threading axel yesterday, I assumed that the code would be safe. But now I am wondering what prevents a stale read from the cache for one of the variables pa or pb. And would it matter if pa, pb pointed to simple global integer variables rather than malloc’d memory? Does the WaitForSingleObject call provide a memory barrier? Or should the pointers be declared volatile? So many questions, so few sentences.

Update: I finally located information that does specifically say that functions that signal synchronization objects do use memory barriers. It should have been obvious, but I was having trouble finding a definitive answer. So I can once again delude myself into believing I understand it all.

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;
}

解决方案

It doesn't matter where the memory lies, and if it were all about cache coherency, then declaring the variables volatile would do nothing to fix it. Volatile's semantics are neither necessary nor sufficient for thread-safety; don't use it!

At the C/C++ level, pa and pb may be cached in registers, but they will be considered stale after any function call. At the CPU level, all wait functions use barriers to make sure everything works as expected.

这篇关于是否WaitForSingleObject的充当内存屏障?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆