Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Objekt mutex můžete použít k ochraně sdíleného prostředku před souběžným přístupem několika vlákny nebo procesy. Každé vlákno musí před spuštěním kódu, který přistupuje ke sdílenému prostředku, nejprve získat mutex. Pokud například několik vláken sdílí přístup k databázi, mohou vlákna použít objekt mutex k povolení zápisu do databáze pouze jedním vláknem najednou.
Následující příklad používá funkci CreateMutex k vytvoření objektu mutex a CreateThread funkce k vytvoření pracovních vláken.
Když vlákno tohoto procesu zapisuje do databáze, nejprve si vyžádá vlastnictví objektu mutex pomocí funkce WaitForSingleObject. Pokud vlákno získá vlastnictví mutexu, zapíše do databáze a poté uvolní vlastnictví mutexu pomocí funkce ReleaseMutex.
Warning
Riziko zablokování při použití časového limitu INFINITE: Níže uvedený příklad používá INFINITE jako parametr časového limitu pro funkci WaitForSingleObject. V produkčním kódu to znamená, že volající vlákno zůstane zablokované na neurčito, pokud vlákno, které mutex vlastní, uvízne v zablokování, přestane reagovat nebo mutex neuvolní. Zvažte použití konečné hodnoty časového limitu a implementaci logiky opakování s diagnostickým protokolováním k detekci potenciálních zablokování. K diagnostice uváznutí mutexu použijte nástroje, jako jsou rozšíření ladicího programu !handle (např. !handle <handle> f) nebo procházení řetězce čekání (GetThreadWaitChain).
Tento příklad používá strukturované zpracování výjimek k zajištění toho, aby vlákno správně uvolní objekt mutex. Blok __finally kódu se spustí bez ohledu na to, jak se blok __try ukončí (pokud blok __try neobsahuje volání funkce TerminateThread ). Tím zabráníte neúmyslně opuštění objektu mutex.
Pokud je mutex opuštěn, vlákno, které mutex vlastnilo, jej před ukončením řádně neuvolnilo. V tomto případě je stav sdíleného prostředku neurčitý a nadále používat mutex může zakrýt potenciálně závažnou chybu. Některé aplikace se mohou pokusit uvést prostředek do konzistentního stavu; tento příklad jednoduše vrátí chybu a mutex již dále nepoužívá. Další informace naleznete v tématu 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;
}