minhas informações de contato
Correspondência[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Índice
Em um ambiente multithread, quando vários threads acessam ou modificam os mesmos dados ao mesmo tempo, o resultado final é o tempo de execução do thread.
Se não houver mecanismo de sincronização, ocorrerão condições de corrida, o que poderá levar a dados imprecisos ou exceções de programa.
- #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) é usado para evitar que vários threads acessem ou modifiquem recursos compartilhados ao mesmo tempo.
Apenas um thread pode possuir o mutex ao mesmo tempo. Se um thread assumir a propriedade do mutex, outros threads que solicitarem o mutex serão bloqueados até que a permissão do mutex seja liberada.
Crie um mutex - CreateMutex
Solicitar mutex - WaitForSingleObject
Libere o 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;
- }
seção Crítica
Mecanismo de sincronização de threads para recursos compartilhados, seções críticas fornecem acesso mutuamente exclusivo entre threads do mesmo processo.
Cada thread deve ser capaz de entrar na seção crítica antes de acessar recursos compartilhados e sair da seção crítica após a conclusão do acesso para concluir a sincronização do thread.
mutex
O mecanismo de sincronização de threads é usado para restringir o acesso de vários threads a recursos compartilhados ao mesmo tempo.
- #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;
- }
desempenho
As seções críticas são mais rápidas que os mutexes em threads do mesmo processo.
Função
Os mutexes podem ser sincronizados entre processos, mas seções críticas só podem ser sincronizadas entre threads no mesmo processo.
propriedade
Mutexes têm requisitos rígidos de propriedade e somente threads com permissões mutex podem liberá-los.
- #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;
- }
Um semáforo é um objeto de sincronização usado para controlar o acesso a recursos compartilhados por vários threads. É um contador que representa a quantidade de recursos disponíveis. Quando o valor do semáforo é maior que 0, indica que há recursos disponíveis; quando o valor é 0, indica que não há recursos disponíveis;
espere : Tenta diminuir o valor do semáforo. Se o valor do semáforo for maior que 0, diminua-o em 1 e continue a execução. Se o valor do semáforo for 0, o thread será bloqueado até que o valor do semáforo seja maior que 0.
libertado : Aumenta o valor do semáforo. Caso existam outras threads bloqueadas aguardando este semáforo, uma delas será despertada.
Criar semáforo
Em sistemas Windows, use CreateSemaphore
ouCreateSemaphoreEx
A função cria um semáforo.
Espere (Espere) e solte (Libere) semáforo
A espera em um semáforo geralmente é feita usando WaitForSingleObject
ouWaitForMultipleObjects
função.
Liberar uso de semáforo ReleaseSemaphore
função.
- #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;
- }
Na programação do Windows, os eventos são um mecanismo de sincronização usado para enviar sinais entre vários threads.O objeto de evento pode serreinicialização manualoureinicialização automática。
Evento de reinicialização manual: quando um evento é definido (sinalizado), ele permanecerá neste estado até ser explicitamente redefinido. Isso significa que vários threads que aguardam o evento podem ser despertados antes que o evento seja redefinido.
Evento de reinicialização automática: quando um evento é recebido (sinalizado) por um thread em espera, o sistema redefine automaticamente o estado do evento para não sinalizado (não sinalizado). Isso significa que apenas um thread pode ser despertado por vez.
Criar Evento
Usando funções da API do WindowsCreateEvent
Um objeto de evento pode ser criado
lpEventAttributes
: Ponteiro para o atributo de segurança, se definido comoNULL
, a segurança padrão será usada.
bManualReset
: seTRUE
, um evento de reinicialização manual será criado; caso contrário, um evento de reinicialização automática será criado.
bInitialState
: seTRUE
, então o estado inicial é o estado do sinal;FALSE
, é um estado sem sinalização.
lpName
: O nome do evento.
Para definir um evento (definir o estado do evento para o estado do sinal), useSetEvent
função
Para redefinir um evento (definir o estado do evento para um estado não sinalizado) useResetEvent
função
Aguarde o evento aguardar que um objeto de evento se torne um estado de sinal.WaitForSingleObject
função
- #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;
- }