моя контактная информация
Почтамезофия@protonmail.com
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Оглавление
В многопоточной среде, когда несколько потоков одновременно обращаются к одним и тем же данным или изменяют их, конечным результатом является время выполнения потока.
Если механизм синхронизации отсутствует, возникнут состояния гонки, что может привести к неточным данным или программным исключениям.
- #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) используется для предотвращения одновременного доступа нескольких потоков к общим ресурсам или их изменения.
Одновременно только один поток может владеть мьютексом. Если один поток становится владельцем мьютекса, другие потоки, запрашивающие мьютекс, будут заблокированы до тех пор, пока не будет освобождено разрешение мьютекса.
Создать мьютекс — CreateMutex
Запросить мьютекс — WaitForSingleObject
Освободить мьютекс — 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;
- }
критическая секция
Механизм синхронизации потоков для общих ресурсов, критические секции обеспечивают взаимоисключающий доступ между потоками одного и того же процесса.
Каждый поток должен иметь возможность войти в критический раздел перед доступом к общим ресурсам и покинуть критический раздел после завершения доступа для завершения синхронизации потоков.
мьютекс
Механизм синхронизации потоков используется для ограничения одновременного доступа нескольких потоков к общим ресурсам.
- #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;
- }
производительность
Критические секции работают быстрее, чем мьютексы внутри потоков одного и того же процесса.
Функция
Мьютексы можно синхронизировать между процессами, но критические секции можно синхронизировать только между потоками одного и того же процесса.
владение
Мьютексы имеют строгие требования к владению, и только потоки с разрешениями на мьютексы могут освободить их.
- #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;
- }
Семафор — это объект синхронизации, используемый для управления доступом к общим ресурсам несколькими потоками. Это счетчик, который отображает количество доступных ресурсов. Когда значение семафора больше 0, это указывает на то, что ресурсы доступны; когда значение равно 0, это указывает на отсутствие доступных ресурсов.
ждать : пытается уменьшить значение семафора. Если значение семафора больше 0, уменьшите его на 1 и продолжите выполнение. Если значение семафора равно 0, поток блокируется до тех пор, пока значение семафора не станет больше 0.
освобожден : Увеличение значения семафора. Если есть другие потоки, заблокированные в ожидании этого семафора, один из них будет разбужен.
Создать семафор
В системах Windows используйте CreateSemaphore
илиCreateSemaphoreEx
Функция создает семафор.
Подождите (Wait) и отпустите (Release) семафор
Ожидание семафора обычно выполняется с помощью WaitForSingleObject
илиWaitForMultipleObjects
функция.
Освободить использование семафора ReleaseSemaphore
функция.
- #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;
- }
В программировании Windows события — это механизм синхронизации, используемый для отправки сигналов между несколькими потоками.Объект события может бытьручной сбросилиавтоматический сброс。
Событие ручного сброса: когда событие установлено (сигнализировано), оно останется в этом состоянии до тех пор, пока не будет явно сброшено. Это означает, что несколько потоков, ожидающих события, могут быть пробуждены до того, как событие будет сброшено.
Событие автоматического сброса: когда событие получено (сигнализировано) ожидающим потоком, система автоматически сбрасывает состояние события на несигнализированное (несигнализированное). Это означает, что одновременно может быть пробуждён только один поток.
Создать событие
Использование функций Windows APICreateEvent
Объект события может быть создан
lpEventAttributes
: Указатель на атрибут безопасности, если установлено значениеNULL
, используется безопасность по умолчанию.
bManualReset
: еслиTRUE
, то создается событие ручного сброса, в противном случае создается событие автоматического сброса.
bInitialState
: еслиTRUE
, то начальное состояние является состоянием сигнала, если;FALSE
, это несигнальное состояние.
lpName
: Название события.
Чтобы установить событие (установить состояние события в состояние сигнала), используйтеSetEvent
функция
Чтобы сбросить событие (установить состояние события в несигнальное состояние), используйтеResetEvent
функция
Подождите, пока событие дождется, пока объект события перейдет в состояние сигнала.WaitForSingleObject
функция
- #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;
- }