Aracılığıyla paylaş


Mutex Nesnelerini Kullanma

Paylaşılan bir kaynağı birden çok iş parçacığı veya işlem tarafından eşzamanlı erişime karşı korumak için bir mutex nesnesi kullanabilirsiniz. Paylaşılan kaynağa erişen kodu yürütebilmesi için her iş parçacığının mutex'in sahipliğini beklemesi gerekir. Örneğin, birkaç iş parçacığı veritabanına erişimi paylaşıyorsa, iş parçacıkları aynı anda yalnızca bir iş parçacığının veritabanına yazmasına izin vermek için bir mutex nesnesi kullanabilir.

Aşağıdaki örnek, bir mutex nesnesi oluşturmak için CreateMutex işlevini ve çalışan iş parçacıkları oluşturmak için createThreadişlevinikullanır.

Bu işlemin bir iş parçacığı veritabanına yazdığında, ilk olarak WaitForSingleObject işlevini kullanarak mutex'in sahipliğini talep eder. İş parçacığı mutex'in sahipliğini alırsa veritabanına yazar ve ReleaseMutex işlevini kullanarak mutex sahipliğini serbest bırakır.

Bu örnek, iş parçacığının mutex nesnesini düzgün bir şekilde serbest bıraktığından emin olmak için yapılandırılmış özel durum işlemeyi kullanır. __try bloğu nasıl sonlandırılırsa sonlandırılsın, kod __finally bloğu her durumda yürütülür (ancak __try bloğu TerminateThread işlevine çağrı içeriyorsa yürütülmez). Bu, mutex nesnesinin yanlışlıkla terk edilmesini engeller.

Bir mutex terk edilirse, mutex'e sahip olan iş parçacığı onu sonlandırmadan önce düzgün bir şekilde serbest bırakmamıştır. Bu durumda, paylaşılan kaynağın durumu belirsizdir ve mutex'i kullanmaya devam etmek ciddi olabilecek bir hatayı gizler. Bazı uygulamalar kaynağı tutarlı bir duruma geri yüklemeye çalışabilir; Bu örnek yalnızca bir hata döndürür ve mutex'i kullanmayı durdurur. Daha fazla bilgi için bkz. Mutex Objects.

#include <windows.h>
#include <stdio.h>

#define THREADCOUNT 2

HANDLE ghMutex; 

DWORD WINAPI WriteToDatabase( LPVOID );

int main( void )
{
    HANDLE aThread[THREADCOUNT];
    DWORD ThreadID;
    int i;

    // Create a mutex with no initial owner

    ghMutex = CreateMutex( 
        NULL,              // default security attributes
        FALSE,             // initially not owned
        NULL);             // unnamed mutex

    if (ghMutex == NULL) 
    {
        printf("CreateMutex error: %d\n", GetLastError());
        return 1;
    }

    // Create worker threads

    for( i=0; i < THREADCOUNT; i++ )
    {
        aThread[i] = CreateThread( 
                     NULL,       // default security attributes
                     0,          // default stack size
                     (LPTHREAD_START_ROUTINE) WriteToDatabase, 
                     NULL,       // no thread function arguments
                     0,          // default creation flags
                     &ThreadID); // receive thread identifier

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

    // Wait for all threads to terminate

    WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE);

    // Close thread and mutex handles

    for( i=0; i < THREADCOUNT; i++ )
        CloseHandle(aThread[i]);

    CloseHandle(ghMutex);

    return 0;
}

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

    DWORD dwCount=0, dwWaitResult; 

    // Request ownership of mutex.

    while( dwCount < 20 )
    { 
        dwWaitResult = WaitForSingleObject( 
            ghMutex,    // handle to mutex
            INFINITE);  // no time-out interval
 
        switch (dwWaitResult) 
        {
            // The thread got ownership of the mutex
            case WAIT_OBJECT_0: 
                __try { 
                    // TODO: Write to the database
                    printf("Thread %d writing to database...\n", 
                            GetCurrentThreadId());
                    dwCount++;
                } 

                __finally { 
                    // Release ownership of the mutex object
                    if (! ReleaseMutex(ghMutex)) 
                    { 
                        // Handle error.
                    } 
                } 
                break; 

            // The thread got ownership of an abandoned mutex
            // The database is in an indeterminate state
            case WAIT_ABANDONED: 
                return FALSE; 
        }
    }
    return TRUE; 
}