2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Sisällysluettelo
Monisäikeisessä ympäristössä, kun useat säikeet käyttävät tai muokkaavat samaa dataa samanaikaisesti, lopputulos on säikeen suoritusaika.
Jos synkronointimekanismia ei ole, esiintyy kilpailuolosuhteita, jotka voivat johtaa epätarkkoihin tietoihin tai ohjelmapoikkeuksiin.
- #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;
- }
Mutexia (Mutex) käytetään estämään useita säikeitä pääsemästä tai muokkaamaan jaettuja resursseja samanaikaisesti.
Vain yksi säie voi omistaa mutexin samanaikaisesti. Jos yksi säie omistaa mutexin, muut mutexia pyytävät säikeet estetään, kunnes mutex-lupa vapautetaan.
Luo mutex - CreateMutex
Pyydä mutexia - WaitForSingleObject
Vapauta 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;
- }
kriittinen jakso
Jaettujen resurssien säikeiden synkronointimekanismi, kriittiset osat tarjoavat toisensa poissulkevan pääsyn saman prosessin säikeiden välillä.
Jokaisen säikeen on kyettävä siirtymään kriittiseen osioon ennen jaettujen resurssien käyttöä ja poistumaan kriittisestä osiosta käyttöoikeuden päätyttyä, jotta säikeen synkronointi on valmis.
mutex
Säikeiden synkronointimekanismia käytetään rajoittamaan useita säikeitä pääsemästä jaettuihin resursseihin samanaikaisesti.
- #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;
- }
esitys
Kriittiset osat ovat nopeampia kuin mutexit saman prosessin säikeissä.
Toiminto
Mutexes voidaan synkronoida prosessien välillä, mutta kriittiset osat voidaan synkronoida vain säikeiden välillä samassa prosessissa.
omistus
Mutexeilla on tiukat omistusvaatimukset, ja vain säikeet, joilla on mutex-oikeudet, voivat vapauttaa sen.
- #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;
- }
Semafori on synkronointiobjekti, jota käytetään hallitsemaan useiden säikeiden pääsyä jaettuihin resursseihin. Se on laskuri, joka edustaa käytettävissä olevien resurssien määrää. Kun semaforin arvo on suurempi kuin 0, se osoittaa, että resurssit ovat käytettävissä, kun arvo on 0, se osoittaa, että resursseja ei ole käytettävissä.
odota : Yrittää pienentää semaforin arvoa. Jos semaforin arvo on suurempi kuin 0, vähennä sitä yhdellä ja jatka suorittamista. Jos semaforin arvo on 0, lanka blokkaa, kunnes semaforin arvo on suurempi kuin 0.
vapautettu : Lisää semaforin arvoa. Jos muita lankoja on estetty odottamassa tätä semaforia, yksi niistä herää.
Luo semafori
Windows-järjestelmissä käytä CreateSemaphore
taiCreateSemaphoreEx
Funktio luo semaforin.
Odota (Odota) ja vapauta (Vapauta) semafori
Semaforin odottaminen tapahtuu yleensä käyttämällä WaitForSingleObject
taiWaitForMultipleObjects
toiminto.
Vapauta semaforien käyttö ReleaseSemaphore
toiminto.
- #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-ohjelmoinnissa tapahtumat ovat synkronointimekanismi, jota käytetään signaalien lähettämiseen useiden säikeiden välillä.Tapahtumaobjekti voi ollamanuaalinen nollaustaiautomaattinen nollaus。
Manuaalinen nollaustapahtuma: Kun tapahtuma on asetettu (signaloitu), se pysyy tässä tilassa, kunnes se nollataan erikseen. Tämä tarkoittaa, että useita tapahtumaa odottavia säikeitä voidaan herättää ennen kuin tapahtuma nollataan.
Automaattinen nollaustapahtuma: Kun odottava säie vastaanottaa (signaloitu) tapahtuman, järjestelmä palauttaa automaattisesti tapahtuman tilan signaloimattomaan (signaloitumattomaan). Tämä tarkoittaa, että vain yksi lanka saa herättää kerrallaan.
Luo tapahtuma
Windows API -toimintojen käyttäminenCreateEvent
Tapahtumaobjekti voidaan luoda
lpEventAttributes
: Osoitin suojausattribuutille, jos se on asetettuNULL
, käytetään oletussuojausta.
bManualReset
: josTRUE
, sitten luodaan manuaalinen nollaustapahtuma, muuten luodaan automaattinen nollaustapahtuma.
bInitialState
: josTRUE
, niin alkutila on signaalin tila;FALSE
, se on ei-signaloiva tila.
lpName
: Tapahtuman nimi.
Aseta tapahtuma (asettaa tapahtuman tila signaalitilaan) käyttämälläSetEvent
toiminto
Voit nollata tapahtuman (asettaa tapahtuman tilaksi ei-signaloidun tilan) käyttämälläResetEvent
toiminto
Odota, että tapahtuma odottaa, että tapahtumaobjektista tulee signaalitila.WaitForSingleObject
toiminto
- #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;
- }