내 연락처 정보
우편메소피아@프로톤메일.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 API 함수 사용CreateEvent
이벤트 객체를 생성할 수 있습니다.
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;
- }