2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Inhaltsverzeichnis
Kritischer Abschnitt und Mutex
Wenn in einer Multithread-Umgebung mehrere Threads gleichzeitig auf dieselben Daten zugreifen oder diese ändern, ist das Endergebnis die Thread-Ausführungszeit.
Wenn kein Synchronisierungsmechanismus vorhanden ist, treten Race Conditions auf, die zu ungenauen Daten oder Programmausnahmen führen können.
- #include <iostream>
- #include <windows.h>
-
- DWORD g_Num = 0;
-
- DWORD WINAPI WorkThread(LPVOID lp)
- {
- for (size_t i = 0; i < 10000000; i++)
- {
- //g_Num++;
- __asm LOCK INC [g_Num]
- }
- return 0;
- }
-
- int main()
- {
- HANDLE hThread[2] = { 0 };
- hThread[0] = CreateThread(NULL, 0, WorkThread, NULL, 0, NULL);
- hThread[1] = CreateThread(NULL, 0, WorkThread, NULL, 0, NULL);
- WaitForMultipleObjects(2, hThread, TRUE, -1);
- std::cout << g_Num << std::endl;
-
- return 0;
- }
- #include <iostream>
- #include <windows.h>
-
- DWORD g_Num = 0;
- CRITICAL_SECTION cs = { 0 };
-
- DWORD WINAPI WorkThread(LPVOID lp)
- {
- for (size_t i = 0; i < 1000000; i++)
- {
- // 进入临界区
- EnterCriticalSection(&cs);
-
- // TODO
- g_Num++;
-
- // 退出临界区
- LeaveCriticalSection(&cs);
- }
- return 0;
- }
-
- int main()
- {
-
- HANDLE hThread[2] = { 0 };
- // 初始临界区
- InitializeCriticalSection(&cs);
-
- hThread[0] = CreateThread(NULL, 0, WorkThread, NULL, 0, NULL);
- hThread[1] = CreateThread(NULL, 0, WorkThread, NULL, 0, NULL);
-
- WaitForMultipleObjects(2, hThread, TRUE, -1);
-
- std::cout << g_Num << std::endl;
-
- // 清理临界区
- DeleteCriticalSection(&cs);
-
- return 0;
- }
Mutex (Mutex) wird verwendet, um zu verhindern, dass mehrere Threads gleichzeitig auf gemeinsam genutzte Ressourcen zugreifen oder diese ändern.
Nur ein Thread kann gleichzeitig Eigentümer des Mutex sein. Wenn ein Thread den Besitz des Mutex übernimmt, werden andere Threads, die den Mutex anfordern, blockiert, bis die Mutex-Berechtigung freigegeben wird.
Erstellen Sie einen Mutex – CreateMutex
Mutex anfordern – WaitForSingleObject
Geben Sie den Mutex frei – ReleaseMutex
- #include <iostream>
- #include <windows.h>
-
- HANDLE hMutex = 0;
- DWORD g_Num = 0;
-
- DWORD WINAPI WorkThread(LPVOID lp)
- {
- for (size_t i = 0; i < 100000; i++)
- {
- WaitForSingleObject(hMutex, INFINITE);
- g_Num++;
- ReleaseMutex(hMutex);
- }
-
- return 0;
- }
-
- int main()
- {
- hMutex = CreateMutex(NULL, FALSE, NULL);
-
- HANDLE hThread1 = CreateThread(NULL, 0, WorkThread, NULL, 0, NULL);
- HANDLE hThread2 = CreateThread(NULL, 0, WorkThread, NULL, 0, NULL);
-
- WaitForSingleObject(hThread1, INFINITE);
- WaitForSingleObject(hThread2, INFINITE);
-
- CloseHandle(hThread1);
- CloseHandle(hThread2);
- CloseHandle(hMutex);
-
- std::cout << g_Num << std::endl;
-
- return 0;
- }
Kritischer Abschnitt
Thread-Synchronisierungsmechanismus für gemeinsam genutzte Ressourcen. Kritische Abschnitte bieten gegenseitig exklusiven Zugriff zwischen Threads desselben Prozesses.
Jeder Thread muss in der Lage sein, den kritischen Abschnitt zu betreten, bevor er auf gemeinsam genutzte Ressourcen zugreift, und den kritischen Abschnitt nach Abschluss des Zugriffs zu verlassen, um die Thread-Synchronisierung abzuschließen.
Mutex
Der Thread-Synchronisierungsmechanismus wird verwendet, um zu verhindern, dass mehrere Threads gleichzeitig auf gemeinsam genutzte Ressourcen zugreifen.
- #include <iostream>
- #include <Windows.h>
-
- int main()
- {
- HANDLE hMutex = CreateMutex(NULL, FALSE, L"0xCC_Mutex");
- if (hMutex == NULL) return 0;
- if (GetLastError() == ERROR_ALREADY_EXISTS)
- {
- MessageBox(NULL, L"禁止多开", L"错误", MB_OKCANCEL);
- return 0;
- }
- std::cout << "Game Start..." << std::endl;
- system("pause");
- CloseHandle(hMutex);
- return 0;
- }
Leistung
Kritische Abschnitte sind schneller als Mutexe innerhalb von Threads desselben Prozesses.
Funktion
Mutexe können prozessübergreifend synchronisiert werden, kritische Abschnitte können jedoch nur zwischen Threads im selben Prozess synchronisiert werden.
Eigentum
Für Mutexe gelten strenge Eigentumsanforderungen und nur Threads mit Mutex-Berechtigungen können sie freigeben.
- #include <iostream>
- #include <Windows.h>
-
- CRITICAL_SECTION CriticalSection = { 0 };
-
- DWORD WINAPI WorkThread(LPVOID lp)
- {
- EnterCriticalSection(&CriticalSection);
-
- printf("TID -> %d rn", GetCurrentThreadId());
- Sleep(5000);
-
- LeaveCriticalSection(&CriticalSection);
-
- return 0;
- }
-
- int main()
- {
- InitializeCriticalSection(&CriticalSection);
-
- HANDLE hThread1 = CreateThread(NULL, 0, WorkThread, NULL, 0, NULL);
- Sleep(1000);
- TerminateThread(hThread1, 1);
-
- HANDLE hThread2 = CreateThread(NULL, 0, WorkThread, NULL, 0, NULL);
- WaitForSingleObject(hThread2, INFINITE);
-
- DeleteCriticalSection(&CriticalSection);
-
- return 0;
- }
- #include <iostream>
- #include <Windows.h>
-
- HANDLE hMutex = NULL;
-
- DWORD WINAPI WorkThread1(LPVOID lp)
- {
- WaitForSingleObject(hMutex, INFINITE);
- printf("TID -> %d rn", GetCurrentThreadId());
- Sleep(5000);
- TerminateThread(GetCurrentThread(), -1);
-
- //todo
- return 0;
- }
-
- DWORD WINAPI WorkThread2(LPVOID lp)
- {
- printf("Wait For Thread1 Leavern");
- WaitForSingleObject(hMutex, INFINITE);
- printf("TID -> %d rn", GetCurrentThreadId());
- ReleaseMutex(hMutex);
- return 0;
- }
-
-
- int main()
- {
- hMutex = CreateMutex(NULL, FALSE, NULL);
-
- HANDLE hThread1 = CreateThread(NULL, 0, WorkThread1, NULL, 0, NULL);
- Sleep(1000);
-
- HANDLE hThread2 = CreateThread(NULL, 0, WorkThread2, NULL, 0, NULL);
- WaitForSingleObject(hThread2, INFINITE);
-
- CloseHandle(hMutex);
- CloseHandle(hThread1);
- CloseHandle(hThread2);
-
- return 0;
- }
Ein Semaphor ist ein Synchronisationsobjekt, mit dem der Zugriff mehrerer Threads auf gemeinsam genutzte Ressourcen gesteuert wird. Es handelt sich um einen Zähler, der die Menge der verfügbaren Ressourcen darstellt. Wenn der Wert des Semaphors größer als 0 ist, bedeutet dies, dass Ressourcen verfügbar sind. Wenn der Wert 0 ist, bedeutet dies, dass keine Ressourcen verfügbar sind.
Warten : Versucht, den Wert des Semaphors zu verringern. Wenn der Wert des Semaphors größer als 0 ist, verringern Sie ihn um 1 und fahren Sie mit der Ausführung fort. Wenn der Wert des Semaphors 0 ist, blockiert der Thread, bis der Wert des Semaphors größer als 0 wird.
befreit : Erhöhen Sie den Wert des Semaphors. Wenn andere Threads blockiert sind und auf dieses Semaphor warten, wird einer von ihnen geweckt.
Semaphor erstellen
Auf Windows-Systemen verwenden Sie CreateSemaphore
oderCreateSemaphoreEx
Funktion erstellt ein Semaphor.
Warten (Wait) und Freigabe (Release) Semaphor
Das Warten auf ein Semaphor erfolgt normalerweise mit WaitForSingleObject
oderWaitForMultipleObjects
Funktion.
Geben Sie die Verwendung von Semaphoren frei ReleaseSemaphore
Funktion.
- #include <iostream>
- #include <Windows.h>
-
- #define MAX_COUNT_SEMAPHORE 3
-
-
- HANDLE g_SemapHore = NULL;
- HANDLE g_hThreadArr[10] = { 0 };
-
- DWORD WINAPI WorkThread(LPVOID lp)
- {
- WaitForSingleObject(g_SemapHore, INFINITE);
-
- for (size_t i = 0; i < 10; i++)
- {
- std::cout << "COUNT -> " << (int)lp << std::endl;
- Sleep(500);
- }
-
- ReleaseSemaphore(g_SemapHore, 1, NULL);
-
- return 0;
- }
-
- int main()
- {
- g_SemapHore = CreateSemaphore(
- NULL, //安全属性
- MAX_COUNT_SEMAPHORE, //初始计数
- MAX_COUNT_SEMAPHORE, //最大计数
- NULL //信号名称
- );
-
- if (g_SemapHore == NULL)
- {
- std::cout << GetLastError() << std::endl;
- return 1;
- }
-
- for (size_t i = 0; i < 10; i++)
- {
- g_hThreadArr[i] = CreateThread(
- NULL,
- 0,
- WorkThread,
- (LPVOID)i,
- 0,
- NULL
- );
- }
-
- WaitForMultipleObjects(10, g_hThreadArr, TRUE, INFINITE);
-
- //closehandle
-
- return 0;
- }
In der Windows-Programmierung sind Ereignisse ein Synchronisationsmechanismus, der zum Senden von Signalen zwischen mehreren Threads verwendet wird.Das Ereignisobjekt kann seinManueller ResetoderAutomatischer Reset。
Manuelles Reset-Ereignis: Wenn ein Ereignis gesetzt (signalisiert) wird, bleibt es in diesem Zustand, bis es explizit zurückgesetzt wird. Dies bedeutet, dass mehrere Threads, die auf das Ereignis warten, aktiviert werden können, bevor das Ereignis zurückgesetzt wird.
Ereignis automatisch zurücksetzen: Wenn ein Ereignis von einem wartenden Thread empfangen (signalisiert) wird, setzt das System den Ereignisstatus automatisch auf nicht signalisiert (nicht signalisiert) zurück. Dies bedeutet, dass jeweils nur ein Thread aktiviert werden darf.
Veranstaltung erstellen
Verwendung von Windows-API-FunktionenCreateEvent
Es kann ein Ereignisobjekt erstellt werden
lpEventAttributes
: Zeiger auf Sicherheitsattribut, falls festgelegtNULL
, wird die Standardsicherheit verwendet.
bManualReset
: WennTRUE
, dann wird ein manuelles Reset-Ereignis erstellt, andernfalls wird ein automatisches Reset-Ereignis erstellt.
bInitialState
: WennTRUE
, dann ist der Anfangszustand der Signalzustand;FALSE
Es handelt sich um einen nicht signalisierenden Zustand.
lpName
: Der Name des Ereignisses.
Um ein Ereignis festzulegen (Ereignisstatus auf Signalstatus setzen), verwenden SieSetEvent
Funktion
Um ein Ereignis zurückzusetzen (den Ereignisstatus auf einen nicht signalisierten Zustand zu setzen), verwenden SieResetEvent
Funktion
Warten Sie, bis das Ereignis darauf wartet, dass ein Ereignisobjekt in einen Signalzustand übergeht.WaitForSingleObject
Funktion
- #include <iostream>
- #include <Windows.h>
-
- DWORD WINAPI WorkThread(LPVOID lp)
- {
- HANDLE hEvent = *(HANDLE*)lp;
- std::cout << "Thread - " << GetCurrentThreadId() << " Waiting For Event" << std::endl;
- WaitForSingleObject(hEvent, INFINITE);
- std::cout << "Thread - " << GetCurrentThreadId() << " actived" << std::endl;
- return 0;
- }
-
- int main()
- {
- HANDLE hThreads[3] = { 0 };
- HANDLE hEvent = NULL;
-
- hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- if (hEvent == NULL) return 0;
-
- for (size_t i = 0; i < 3; i++)
- {
- hThreads[i] = CreateThread(NULL, 0, WorkThread, &hEvent, 0, NULL);
- }
-
- Sleep(2000);
- SetEvent(hEvent);
-
- WaitForMultipleObjects(3, hThreads, TRUE, INFINITE);
-
- CloseHandle(hEvent);
-
- return 0;
- }