2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Table des matières
Dans un environnement multithread, lorsque plusieurs threads accèdent ou modifient les mêmes données en même temps, le résultat final est le temps d'exécution du thread.
S'il n'y a pas de mécanisme de synchronisation, des conditions de concurrence se produiront, ce qui peut conduire à des données inexactes ou à des exceptions de programme.
- #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) est utilisé pour empêcher plusieurs threads d'accéder ou de modifier des ressources partagées en même temps.
Un seul thread peut posséder le mutex en même temps. Si un thread prend possession du mutex, les autres threads demandant le mutex seront bloqués jusqu'à ce que l'autorisation du mutex soit libérée.
Créer un mutex - CreateMutex
Demander un mutex - WaitForSingleObject
Libérez le mutex - 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;
- }
section critique
Mécanisme de synchronisation des threads pour les ressources partagées, les sections critiques fournissent un accès mutuellement exclusif entre les threads du même processus.
Chaque thread doit pouvoir entrer dans la section critique avant d'accéder aux ressources partagées, et quitter la section critique une fois l'accès terminé pour terminer la synchronisation des threads.
mutex
Le mécanisme de synchronisation des threads est utilisé pour empêcher plusieurs threads d'accéder aux ressources partagées en même temps.
- #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;
- }
performance
Les sections critiques sont plus rapides que les mutex au sein des threads du même processus.
Fonction
Les mutex peuvent être synchronisés entre les processus, mais les sections critiques ne peuvent être synchronisées qu'entre les threads du même processus.
la possession
Les mutex ont des exigences de propriété strictes, et seuls les threads disposant d'autorisations mutex peuvent les publier.
- #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;
- }
Un sémaphore est un objet de synchronisation utilisé pour contrôler l'accès aux ressources partagées par plusieurs threads. C'est un compteur qui représente la quantité de ressources disponibles. Lorsque la valeur du sémaphore est supérieure à 0, cela indique que des ressources sont disponibles ; lorsque la valeur est 0, cela indique qu'aucune ressource n'est disponible.
attendez : Tente de diminuer la valeur du sémaphore. Si la valeur du sémaphore est supérieure à 0, décrémentez-la de 1 et poursuivez l'exécution. Si la valeur du sémaphore est 0, le thread se bloque jusqu'à ce que la valeur du sémaphore devienne supérieure à 0.
libéré : Augmente la valeur du sémaphore. S'il y a d'autres threads bloqués en attente de ce sémaphore, l'un d'eux sera réveillé.
Créer un sémaphore
Sur les systèmes Windows, utilisez CreateSemaphore
ouCreateSemaphoreEx
La fonction crée un sémaphore.
Attendez (Attendez) et relâchez (Release) le sémaphore
L'attente d'un sémaphore se fait généralement en utilisant WaitForSingleObject
ouWaitForMultipleObjects
fonction.
Libérer l'utilisation du sémaphore ReleaseSemaphore
fonction.
- #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;
- }
Dans la programmation Windows, les événements sont un mécanisme de synchronisation utilisé pour envoyer des signaux entre plusieurs threads.L'objet événement peut êtreréinitialisation manuelleouréinitialisation automatique。
Événement de réinitialisation manuelle : lorsqu'un événement est défini (signalé), il restera dans cet état jusqu'à ce qu'il soit explicitement réinitialisé. Cela signifie que plusieurs threads en attente de l'événement peuvent être réveillés avant que l'événement ne soit réinitialisé.
Événement de réinitialisation automatique : lorsqu'un événement est reçu (signalé) par un thread en attente, le système réinitialise automatiquement l'état de l'événement sur non signalé (non signalé). Cela signifie qu'un seul thread peut être réveillé à la fois.
Créer un évènement
Utilisation des fonctions de l'API WindowsCreateEvent
Un objet événement peut être créé
lpEventAttributes
: Pointeur vers l'attribut de sécurité, s'il est défini surNULL
, la sécurité par défaut est utilisée.
bManualReset
: siTRUE
, alors un événement de réinitialisation manuelle est créé, sinon un événement de réinitialisation automatique est créé.
bInitialState
: siTRUE
, alors l'état initial est l'état du signal si ;FALSE
, c'est un état sans signalisation.
lpName
: Le nom de l'évènement.
Pour définir un événement (définir l'état de l'événement sur l'état du signal), utilisezSetEvent
fonction
Pour réinitialiser un événement (définir l'état de l'événement sur un état non signalé), utilisezResetEvent
fonction
Attendez que l'événement attende qu'un objet événement devienne un état de signal.WaitForSingleObject
fonction
- #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;
- }