//设置信号量 2 个资源 2 同时只可以有两个线程访问 global_Semephore= CreateSemaphore(NULL, 2, 2, NULL); this->StartThread(); // TODO: Add your control notification handler code here } void CSemaphoreDlg::OnBnClickedButtonThree() { //设置信号量 3 个资源 3 同时只可以有三个线程访问 global_Semephore= CreateSemaphore(NULL, 3, 3, NULL); this->StartThread(); // TODO: Add your control notification handler code here } 信号量的使用特点使其更适用于对Socket(套接字)程序中线程的同步。例如,网络上的HTTP服务器要对同一时间内访问同一页面的用户数加以限制,这时可以为每一个用户对服务器的页面请求设置一个线程,而页面则是待保护的共享资源,通过使用信号量对线程的同步作用可以确保在任一时刻无论有多少用户对某一页面进行访问,只有不大于设定的最大用户数目的线程能够进行访问,而其他的访问企图则被挂起,只有在有用户退出对此页面的访问后才有可能进入。 事件(Event)
事件对象也可以通过通知操作的方式来保持线程的同步。并且可以实现不同进程中的线程同步操作。 信号量包含的几个操作原语: CreateEvent() 创建一个信号量 OpenEvent() 打开一个事件 SetEvent() 回置事件 WaitForSingleObject() 等待一个事件 WaitForMultipleObjects() 等待多个事件 WaitForMultipleObjects 函数原型: WaitForMultipleObjects( IN DWORD nCount, // 等待句柄数 IN CONST HANDLE *lpHandles, //指向句柄数组 IN BOOL bWaitAll, //是否完全等待标志 IN DWORD dwMilliseconds //等待时间 ) 参数nCount指定了要等待的内核对象的数目,存放这些内核对象的数组由lpHandles来指向。fWaitAll对指定的这nCount个内核对象的两种等待方式进行了指定,为TRUE时当所有对象都被通知时函数才会返回,为FALSE则只要其中任何一个得到通知就可以返回。dwMilliseconds在这里的作用与在WaitForSingleObject()中的作用是完全一致的。如果等待超时,函数将返回WAIT_TIMEOUT。 代码: //事件数组 HANDLE global_Events[2]; // 共享资源 char global_Array[256]; void InitializeArray() { for(int i = 0;i<256;i++) { global_Array[i]=I; } } UINT Global_ThreadOne(LPVOID pParam) { CEdit *ptr=(CEdit *)pParam; ptr->SetWindowText(""); for(int i = 0;i<256;i++) { global_Array[i]=O; ptr->SetWindowText(global_Array); Sleep(10); } //回置事件 SetEvent(global_Events[0]); return 0; } UINT Global_ThreadTwo(LPVOID pParam) { CEdit *ptr=(CEdit *)pParam; ptr->SetWindowText(""); for(int i = 0;i<256;i++) { global_Array[i]=T; ptr->SetWindowText(global_Array); Sleep(10); } //回置事件 SetEvent(global_Events[1]); return 0; } UINT Global_ThreadThree(LPVOID pParam) { CEdit *ptr=(CEdit *)pParam; ptr->SetWindowText(""); //等待两个事件都被回置 WaitForMultipleObjects(2, global_Events, true, INFINITE); for(int i = 0;i<256;i++) { global_Array[i]=H; ptr->SetWindowText(global_Array); Sleep(10); } return 0; } void CEventDlg::OnBnClickedButtonStart() { for (int i = 0; i < 2; i++) { //实例化事件 global_Events[i]=CreateEvent(NULL,false,false,NULL); } CWinThread *ptrOne = AfxBeginThread(Global_ThreadOne, &m_One, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED); ptrOne->ResumeThread(); //Start the second Thread CWinThread *ptrTwo = AfxBeginThread(Global_ThreadTwo, &m_Two, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED); ptrTwo->ResumeThread(); //Start the Third Thread CWinThread *ptrThree = AfxBeginThread(Global_ThreadThree, &m_Three, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED); ptrThree->ResumeThread(); |