informasi kontak saya
Surat[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Daftar isi
Dalam lingkungan multi-thread, ketika beberapa thread mengakses atau mengubah data yang sama secara bersamaan, hasil akhirnya adalah waktu eksekusi thread.
Jika tidak ada mekanisme sinkronisasi, kondisi balapan akan terjadi, yang dapat menyebabkan pengecualian data atau program tidak akurat.
- #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) digunakan untuk mencegah beberapa thread mengakses atau memodifikasi sumber daya bersama secara bersamaan.
Hanya satu thread yang dapat memiliki mutex pada saat yang sama. Jika satu thread mengambil alih kepemilikan mutex, thread lain yang meminta mutex akan diblokir hingga izin mutex dilepaskan.
Buat mutex - BuatMutex
Minta mutex - WaitForSingleObject
Lepaskan mutex - RilisMutex
- #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;
- }
bagian penting
Mekanisme sinkronisasi thread untuk sumber daya bersama, bagian penting menyediakan akses yang saling eksklusif antara thread dari proses yang sama.
Setiap thread harus dapat memasuki bagian penting sebelum mengakses sumber daya bersama, dan keluar dari bagian penting setelah akses selesai untuk menyelesaikan sinkronisasi thread.
mutex
Mekanisme sinkronisasi thread digunakan untuk membatasi beberapa thread mengakses sumber daya bersama secara bersamaan.
- #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;
- }
pertunjukan
Bagian kritis lebih cepat daripada mutex dalam thread dari proses yang sama.
Fungsi
Mutex dapat disinkronkan antar proses, tetapi bagian penting hanya dapat disinkronkan antar thread dalam proses yang sama.
kepemilikan
Mutex memiliki persyaratan kepemilikan yang ketat, dan hanya thread dengan izin mutex yang dapat melepaskannya.
- #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;
- }
Semaphore adalah objek sinkronisasi yang digunakan untuk mengontrol akses ke sumber daya bersama oleh beberapa thread. Ini adalah penghitung yang mewakili jumlah sumber daya yang tersedia. Jika nilai semaphore lebih besar dari 0, berarti sumber daya tersedia; jika nilainya 0, berarti tidak ada sumber daya yang tersedia.
Tunggu : Upaya untuk menurunkan nilai semaphore. Jika nilai semaphore lebih besar dari 0, kurangi sebesar 1 dan lanjutkan eksekusi. Jika nilai semaphore adalah 0, thread akan diblokir hingga nilai semaphore menjadi lebih besar dari 0.
dibebaskan : Meningkatkan nilai semaphore. Jika ada thread lain yang diblokir menunggu semaphore ini, salah satunya akan dibangunkan.
Buat semafor
Pada sistem Windows, gunakan CreateSemaphore
atauCreateSemaphoreEx
Fungsi membuat semaphore.
Tunggu (Tunggu) dan lepaskan (Lepaskan) semaphore
Menunggu semaphore biasanya dilakukan dengan menggunakan WaitForSingleObject
atauWaitForMultipleObjects
fungsi.
Lepaskan penggunaan semaphore ReleaseSemaphore
fungsi.
- #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;
- }
Dalam pemrograman Windows, event adalah mekanisme sinkronisasi yang digunakan untuk mengirim sinyal antara beberapa thread.Objek acaranya bisa berupapengaturan ulang manualataupengaturan ulang otomatis。
Peristiwa Penyetelan Ulang Manual: Ketika suatu peristiwa disetel (diberi sinyal), peristiwa tersebut akan tetap dalam keadaan ini hingga direset secara eksplisit. Ini berarti beberapa thread yang menunggu acara dapat dibangunkan sebelum acara direset.
Auto Reset Event: Ketika suatu event diterima (ditandai) oleh thread yang menunggu, sistem secara otomatis mereset status event menjadi non-signaled (tidak diberi sinyal). Artinya hanya satu thread yang diperbolehkan untuk dibangunkan dalam satu waktu.
Membuat acara
Menggunakan fungsi Windows APICreateEvent
Objek acara dapat dibuat
lpEventAttributes
: Penunjuk ke atribut keamanan, jika disetel keNULL
, keamanan default digunakan.
bManualReset
: jikaTRUE
, maka peristiwa penyetelan ulang manual akan dibuat, jika tidak, peristiwa penyetelan ulang otomatis akan dibuat.
bInitialState
: jikaTRUE
, maka keadaan awal adalah keadaan sinyal;FALSE
, ini adalah keadaan tanpa sinyal.
lpName
: Nama acara.
Untuk menyetel suatu peristiwa (atur status peristiwa ke status sinyal) gunakanSetEvent
fungsi
Untuk mengatur ulang suatu peristiwa (mengatur keadaan peristiwa ke keadaan non-sinyal) gunakanResetEvent
fungsi
Tunggu event menunggu objek event menjadi status sinyal.WaitForSingleObject
fungsi
- #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;
- }