VC下线程同步的三种方法(互斥、事件、临界区、信号量)
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
// SD bManualReset,
bInitialState,
lpName
lpEventAttributes
一般为 NULL
bManualReset
创建的 Event 是自动复位还是人工复位
来自百度文库
,如果 true,
人工复位,
一旦该 Event 被设置为有信号,则它一直会等到 ResetEvent()API 被调用时才会恢复
VC 下线程同步的三种方法(互斥、事件、临界区、信号量)
学习各种外挂制作技术,马上去百度搜索 "魔鬼作坊" 点击第一个站进入、快速 成为做挂达人。
线程相关函数: _beginthreadex:创建一个线程 SuspendThread:挂起一个线程 ResumeThread:继续一个挂起的线程 Closehandle:释放该线程使用资源 WaitForsingleobject:等待线程结束 TerminateThread:强制线程结束. 首选使用临界区对象,主要原因是使用简单。 EnterCritic alSec tion()函数 等候指定的危险 区段对象的所有权 。当调用的线程 被允许所有 权时,函数返回。 EnterCriticalSection (),一个单独进程的线程可以使用一个危险区段对象作为相互-排除同 步。 进程负责分配被一个危险区段对象使用的内存, 它藉由声明一个 CRITICAL_SECTION 类型 的变量实现。在使用一个危险区段之前,进程的一些线程必须调用 InitializeCriticalSection 函数设定对象的初值. 为 了 要 使 互 斥 的 访 问 被 共 享 的 资 源 , 每 个 线 程 调 用 EnterCriticalSection 或 者 TryEnterCriticalSection 功能,在执行访问被保护资源的任何代码段之前,请求危险区段的 所有权。
PulseEvent()是一个比较有意思的使用方法,正如这个 API 的名字,它使一个 Event 对象 的状 态发生 一次 脉冲变 化, 从无 信号 变成有 信号 再变成 无信 号, 而整 个操 作是原 子 的. 对自动复位的 Event 对象,它仅释放第一个等到该事件的 thread(如果有),而对于 人工复位的 Event 对象,它释放所有等待的 thread. #include <windows.h> #include <iostream> using namespace std; DWORD WINAPI Fun1Proc(LPVOID lpParameter); DWORD WINAPI Fun2Proc(LPVOID lpParameter); int tickets=100; HANDLE g_hEvent; void main()
}
--------------------------------------------------------------------------------
三、使用事件对象 HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL // reset type BOOL // initial state LPCTSTR // object name ); 该函数创建一个 Event 同步对象,并返回该对象的 Handle
为无信号. 如果为 false,Event 被设置为有信号,则当有一个 wait 到它的 Thread 时,
该 Event 就会自动复位,变成无信号.
bInitialState
初始状态,true,有信号,false 无信号
lpName
Event 对象名
一个 Event 被创建以后,可以用 OpenEvent()API 来获得它的 Handle,用 CloseHandle() 来关闭它,用 SetEvent()或 PulseEvent()来设置它使其有信号,用 ResetEvent() 来使其无信号,用 WaitForSingleObject()或 WaitForMultipleObjects()来等待 其变为有信号.
Sleep(1); cout<<"thread1 sell ticket :"<<tickets--<<endl; } else break; ReleaseMutex(hMutex);//设置该互斥对象的线程 ID 为 0,并且将该对象设置为有信号状态 } return 0; } DWORD WINAPI Fun2Proc(LPVOID lpParameter) { while (TRUE) { WaitForSingleObject(hMutex,INFINITE); if (tickets>0) { Sleep(1); cout<<"thread2 sell ticket :"<<tickets--<<endl; } else break; ReleaseMutex(hMutex); } return 0;
} DWORD WINAPI Fun1Proc(LPVOID lpParameter) { while (TRUE) { EnterCriticalSection(&g_csA); Sleep(1); //EnterCriticalSection(&g_csB);//临界区的同步和互锁 if (tickets>0) {
Sleep(1); cout<<"Thread1 sell ticket :"<<tickets--<<endl; //LeaveCriticalSection(&g_csB); LeaveCriticalSection(&g_csA); } else { //LeaveCriticalSection(&g_csB); LeaveCriticalSection(&g_csA); break; } } return 0; } DWORD WINAPI Fun2Proc(LPVOID lpParameter) { while (TRUE) { EnterCriticalSection(&g_csB); Sleep(1); EnterCriticalSection(&g_csA); if (tickets>0) { Sleep(1); cout<<"Thread2 sell ticket :"<<tickets--<<endl; LeaveCriticalSection(&g_csA); LeaveCriticalSection(&g_csB); } else { LeaveCriticalSection(&g_csA); LeaveCriticalSection(&g_csB); break; }
#include <windows.h> #include <iostream> using namespace std; DWORD WINAPI Fun1Proc(LPVOID lpParameter); DWORD WINAPI Fun2Proc(LPVOID lpParameter); int tickets=100; CRITICAL_SECTION g_csA; CRITICAL_SECTION g_csB; void main() { HANDLE hThread1; HANDLE hThread2; hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL); hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL); CloseHandle(hThread1); CloseHandle(hThread2); InitializeCriticalSection(&g_csA); InitializeCriticalSection(&g_csB); Sleep(40000); DeleteCriticalSection(&g_csA); DeleteCriticalSection(&g_csB);
} return 0; }
--------------------------------------------------------------------------------
二、使用互斥对象 DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds); 如果时间是有信号状态返回 WAIT_OBJECT_0,如果时间超过 dwMilliseconds 值但时间事件 还是无信号状态则返回 WAIT_TIMEOUT WaitForSingleObject 函 数用 来 检测 hHandle 事 件的 信 号状 态 ,当 函 数的 执 行时 间 超过 dwMilliseconds 就返回,但如果参数 dwMilliseconds 为 INFINITE 时函数将直到相应时间事 件变成有信号状态才返回,否则就一直等待下去,直到 WaitForSingleObject 有返回直才执行 后面的代码。 #include <windows.h> #include <iostream> using namespace std; DWORD WINAPI Fun1Proc(LPVOID lpParameter); DWORD WINAPI Fun2Proc(LPVOID lpParameter); int index =0; int tickets=100; HANDLE hMutex; void main() { HANDLE hThread1; HANDLE hThread2; //创建线程 hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL); hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL); CloseHandle(hThread1); CloseHandle(hThread2); //************************************************************** //保证应用程序只有一个实例运行,创建一个命名的互斥对象. hMutex=CreateMutex(NULL,TRUE,LPCTSTR("tickets")); //创建时主线程拥有该互斥对象,互斥对象的线程 ID 为主线程的 ID,同时将该互斥对象内部计 数器置为 1 if (hMutex) { if (ERROR_ALREADY_EXISTS==GetLastError()) {
cout<<"only one instance can run!"<<endl; //Sleep(40000); return; }
} //************************************************************** WaitForSingleObject(hMutex,INFINITE); //使用该函数请求互斥对象时,虽说该对象处于无信号状态,但因为请求的线程 ID 和该互斥对 象所有者的线程 ID 是相同的.所以仍然可以请求到这个互斥对象,于是该互斥对象内部计数 器加 1,内部计数器的值为 2. 意思是有两个等待动作 ReleaseMutex(hMutex);//释放一次互斥对象,该互斥对象内部计数器的值递减 1,操作系统不会 将这个互斥对象变为已通知状态. ReleaseMutex(hMutex);//释放一次互斥对象,该互斥对象内部计数器的值为 0,同时将该对象设 置为已通知状态. //对于互斥对象来说,谁拥有谁释放 Sleep(40000); } DWORD WINAPI Fun1Proc(LPVOID lpParameter) { while (TRUE) { WaitForSingleObject(hMutex,INFINITE);//等待互斥对象有信号 if (tickets>0) {