Yesterday, the double-checked lock question launched a line of thought that left me unsure of a simple situation. In the following code, is it possible to click printfin "Don't sync anymore"? In this simple example, the values are likely to be in the same cache line, so I think it will be less likely (assuming the opportunity starts> 0%).
If the answer is: “No, this is impossible,” then my next question is more likely to be predictable: why not? Until yesterday, when my thoughts got confused and wrapped around a multi-threaded axel, I assumed that the code would be safe. But now I'm wondering what prevents obsolete cache reading for one of the variables paor pb. And will it matter if it pa, pbpoints to simple global integer variables, and not to mallocd memory? Does a WaitForSingleObject call cause a memory barrier? Or if pointers are declared unstable? So many questions, so few suggestions.
Refresh . I finally found information that specifically states that functions that use signal synchronization objects use memory barriers . This should have been obvious, but I could not find the final answer. Therefore, I can again deceive myself, believing that I understand everything.
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;
pa = (int*)malloc( sizeof( int ));
pb = (int*)malloc( sizeof( int ));
*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;
}