Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the thread synchronization not work?

I have written a multithreaded program, in which three threads are trying to save the text to the same file. I applied the critical section. And under windows 7 works perfectly but in CE 6.0 does not sync, ie, each thread is trying at the same time to save:

It works now!!! Thanks Everyone for help!

Emulator

Kernel tracker

Critical section:

InitializeCriticalSection(&CriticalSection);

// Create worker threads
for( i=0; i < THREADCOUNT; i++ )
{
    aThread[i] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE) WriteToFile, NULL, 0, &ThreadID);

    if( aThread[i] == NULL )
    {
        printf("CreateThread error: %d\n", GetLastError());
        return 1;
    }
}

// Wait for all threads to terminate
for( i=0; i < THREADCOUNT; i++ )
{
    WaitResult = WaitForSingleObject(aThread[i], INFINITE);

    switch(WaitResult)
    {
        case WAIT_OBJECT_0:
            printf("Thread %d has terminated...\n", i);
         break;

         // Time out
        case WAIT_TIMEOUT:
            printf("The waiting is timed out...\n");
            break;

        // Return value is invalid.
        default:
            printf("Waiting failed, error %d...\n", GetLastError());
            ExitProcess(0);
    }
}

// Close thread handles
for( i=0; i < THREADCOUNT; i++ )
    CloseHandle(aThread[i]);

// Release resources used by the critical section object.
DeleteCriticalSection(&CriticalSection);

Function called by a thread:

DWORD WINAPI WriteToFile( LPVOID lpParam )
{ 
// lpParam not used in this example
UNREFERENCED_PARAMETER(lpParam);

DWORD dwCount=1, dwWaitResult; 

HANDLE hFile; 
char DataBuffer[30];
DWORD dwBytesToWrite;
DWORD dwBytesWritten;

// Request ownership of the critical section.
EnterCriticalSection(&CriticalSection);

    // Write to the file
    printf("Thread %d writing to file...\n", GetCurrentThreadId());

    hFile = CreateFile(TEXT("file.txt"), GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 

    SetFilePointer(hFile, 0, NULL, FILE_END);

    while( dwCount <= 3 )
    {
        sprintf(DataBuffer, "Theard %d writing %d\n", GetCurrentThreadId(), dwCount);
        dwBytesToWrite = (DWORD)strlen(DataBuffer);

        WriteFile( hFile, DataBuffer, dwBytesToWrite, &dwBytesWritten, NULL);

            printf("Theard %d wrote %d successfully.\n", GetCurrentThreadId(), dwCount);
            }
        }

        dwCount++;
    }

CloseHandle(hFile);             

// Release ownership of the critical section.
LeaveCriticalSection(&CriticalSection);

return TRUE; 
}
like image 862
Rafał Avatar asked Dec 28 '22 07:12

Rafał


1 Answers

The problem is that you are passing TRUE to the fWaitAll flag for WaitForMultipleObjects. On Windows CE, this is not supported: the documentation on MSDN says that this flag must be FALSE. WaitForMultipleObjects is thus not waiting, but returning an error instead, but you are not checking the return code. The main thread thus goes straight through, closes the handles and deletes the critical section whilst the "worker" threads are still running. Once DeleteCriticalSection has been called, the critical section "can no longer be used for synchronization", so the EnterCriticalSection calls probably no longer block, and you end up with the scenario you have here.

On Windows 7, everything works because the WaitForMultipleObjects call does indeed wait for all the threads to finish.

Rather than using WaitForMultipleObjects, just use WaitForSingleObject in a loop to wait for each thread in turn.

like image 175
Anthony Williams Avatar answered Jan 10 '23 03:01

Anthony Williams