Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Sie können ein Mutex-Objekt verwenden, um eine freigegebene Ressource vor gleichzeitigem Zugriff durch mehrere Threads oder Prozesse zu schützen. Jeder Thread muss auf den Besitz des Mutex warten, bevor er den Code ausführen kann, der auf die freigegebene Ressource zugreift. Wenn z. B. mehrere Threads den Zugriff auf eine Datenbank teilen, können die Threads ein Mutex-Objekt verwenden, um jeweils nur einen Thread zum Schreiben in die Datenbank zuzulassen.
Im folgenden Beispiel wird die CreateMutex-Funktion verwendet, um ein Mutex-Objekt und die CreateThread-Funktion zum Erstellen von Arbeitsthreads zu erstellen.
Wenn ein Thread dieses Prozesses in die Datenbank schreibt, fordert er zuerst den Besitz des Mutex mithilfe der WaitForSingleObject-Funktion an. Wenn der Thread den Besitz des Mutex erhält, schreibt er in die Datenbank und gibt dann den Besitz des Mutex mithilfe der ReleaseMutex-Funktion frei.
Warnung
Deadlock-Risiko bei INFINITE-Timeout: Das folgende Beispiel verwendet INFINITE als Timeout-Parameter für die Funktion WaitForSingleObject. Im Produktionscode bedeutet dies, dass der aufrufende Thread auf unbestimmte Zeit blockiert wird, wenn der Thread, der den Mutex besitzt, einen Deadlock erleidet, hängt oder den Mutex nicht freigibt. Erwägen Sie die Verwendung eines endlichen Timeoutwerts und implementieren Sie eine Wiederholungslogik mit diagnostischer Protokollierung, um potenzielle Deadlocks zu erkennen. Verwenden Sie Tools wie die !Handle-Debuggererweiterung (z. B. !handle <handle> f) oder Wait Chain Traversal (GetThreadWaitChain), um mutex deadlocks zu diagnostizieren.
In diesem Beispiel wird die strukturierte Ausnahmebehandlung verwendet, um sicherzustellen, dass der Thread das Mutex-Objekt ordnungsgemäß loslässt. Der __finally Codeblock wird unabhängig davon ausgeführt, wie der __try-Block beendet wird (es sei denn, der __try-Block enthält einen Aufruf der TerminateThread-Funktion ). Dadurch wird verhindert, dass das Mutex-Objekt versehentlich aufgegeben wird.
Wenn ein Mutex aufgegeben wurde, hat der Thread, dem der Mutex gehörte, ihn vor seiner Beendigung nicht ordnungsgemäß freigegeben. In diesem Fall ist der Status der freigegebenen Ressource nicht bestimmbar, und die weitere Verwendung des Mutex kann einen potenziell schwerwiegenden Fehler verschleiern. Einige Anwendungen versuchen möglicherweise, die Ressource in einem konsistenten Zustand wiederherzustellen; In diesem Beispiel wird einfach ein Fehler zurückgegeben und die Verwendung des Mutex beendet. Weitere Informationen finden Sie unter 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;
}