昨天一个关于双重检查锁定的问题引发了一连串的思考,让我对一个简单的情况不确定。在下面的代码中,是否可以点击
printf
_不再同步__?在这个简单的示例中,值可能位于同一缓存线上,因此我认为它不太可能(假设可能性从0%开始)。
如果答案是,不,这是不可能的。,那么我的后续问题是,相当可预见的:为什么不呢?直到昨天我的思想被多线程AXEL缠住了,我才认为代码是安全的。但是现在我想知道是什么阻止了对其中一个变量从缓存中进行过时的读取
pa
或
pb
. 如果
pa, pb
指向简单的全局整型变量而不是malloc_d内存?WaitForSingleObject调用是否提供内存屏障?还是应该将指针声明为易失性?问题太多,句子太少。
更新
:我最后找到的信息确实特别说明了信号同步对象确实使用的函数
memory barriers
.这本应该是显而易见的,但我很难找到一个明确的答案。所以我可以再一次欺骗自己,让自己相信我了解这一切。
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;
}