1、VC60做的实现线程同步的四种方法的详细操作步骤VC6.0做的实现线程同步的四种方法的详细操作步骤软件作业一:如何实现线程同步?(二是一个基于单个文档的MFC程序,参考的是某本书上完整的一个可运行实例,所用代码和课件上几乎相同,应该会更符合老师上课讲的思路)windows系统提供的4种同步化机制分别为:临界区信号量内核对象事件内核对象互斥体对象一:非MFC下实现线程同步实例 临界区:课本P43、44/ CriticalSection.cpp文件#include #include #include BOOL g_bContinue = TRUE;int g_nCount1 = 0;int g_n
2、Count2 = 0;CRITICAL_SECTION g_cs; / 对存在同步问题的代码段使用临界区对象UINT _stdcall ThreadFunc(LPVOID);int main(int argc, char* argv) UINT uId; HANDLE h2; / 初始化临界区对象 :InitializeCriticalSection(&g_cs); h0 = (HANDLE):_beginthreadex(NULL, 0, ThreadFunc, NULL, 0, &uId); h1 = (HANDLE):_beginthreadex(NULL, 0, ThreadFunc,
3、 NULL, 0, &uId); / 等待1秒后通知两个计数线程结束,关闭句柄 Sleep(1000); g_bContinue = FALSE; :WaitForMultipleObjects(2, h, TRUE, INFINITE); :CloseHandle(h0); :CloseHandle(h1); / 删除临界区对象 :DeleteCriticalSection(&g_cs); printf(g_nCount1 = %d n, g_nCount1); printf(g_nCount2 = %d n, g_nCount2); return 0;UINT _stdcall Threa
4、dFunc(LPVOID) while(g_bContinue) :EnterCriticalSection(&g_cs); g_nCount1+; g_nCount2+; :LeaveCriticalSection(&g_cs); return 0; 事件内核对象:课本P46/ EventDemo.cpp文件#include #include #include HANDLE g_hEvent;UINT _stdcall ChildFunc(LPVOID);int main(int argc, char* argv) HANDLE hChildThread; UINT uId; / 创建一个自
5、动重置的(auto-reset events),未受信的(nonsignaled)事件内核对象 g_hEvent = :CreateEvent(NULL, FALSE, FALSE, NULL); hChildThread = (HANDLE):_beginthreadex(NULL, 0, ChildFunc, NULL, 0, &uId); / 通知子线程开始工作 printf(Please input a char to tell the Child Thread to work: n); getchar(); :SetEvent(g_hEvent); / 等待子线程完成工作,释放资源
6、:WaitForSingleObject(hChildThread, INFINITE); printf(All the work has been finished. n); :CloseHandle(hChildThread); :CloseHandle(g_hEvent); return 0;UINT _stdcall ChildFunc(LPVOID) :WaitForSingleObject(g_hEvent, INFINITE); printf( Child thread is working. n); :Sleep(5*1000); / 暂停5秒,模拟真正的工作 return 0
7、; 设定优先级实现三个线程的同步(参见课本P38)/ PriorityDemo.cpp文件#include #include HANDLE hMutex = NULL;char g_cArray10;DWORD WINAPI ThreadProc1(LPVOID lpParam) WaitForSingleObject(hMutex,INFINITE); for(int i=0;i10;i+) g_cArrayi=a; printf(ThreadProc1 Normal Thread is runningn); printf(g_cArray%d = %cn,i,g_cArrayi); Sle
8、ep(1000);/sleep(1)约为15ms ReleaseMutex(hMutex); return 0;DWORD WINAPI ThreadProc2(LPVOID lpParam) WaitForSingleObject(hMutex,INFINITE); for(int i=0;i10;i+) g_cArray10-i-1=b; printf(ThreadProc2 Lowest Thread is runningn); printf(g_cArray%d = %cn,10-i-1,g_cArray10-i-1); Sleep(1000); ReleaseMutex(hMutex
9、); return 0;DWORD WINAPI ThreadProc3(LPVOID lpParam) WaitForSingleObject(hMutex,INFINITE); for(int i=0;i10;i+) g_cArrayi=c; printf(ThreadProc3 Idle Thread is runningn); printf(g_cArray%d = %cn,i,g_cArrayi); Sleep(1000); ReleaseMutex(hMutex); return 0;int main(int argc, char* argv) DWORD dwThreadID;
10、HANDLE h3; / 创建一个优先级为Normal的线程 h0 = :CreateThread(NULL, 0, ThreadProc1, NULL, 0, &dwThreadID); / 创建一个优先级为Lowest的线程 h1 = :CreateThread(NULL, 0, ThreadProc2, NULL, CREATE_SUSPENDED, &dwThreadID); :SetThreadPriority(h1, THREAD_PRIORITY_LOWEST); :ResumeThread(h1); / 创建一个优先级为Idle的线程 h2 = :CreateThread(NU
11、LL, 0, ThreadProc3, NULL, CREATE_SUSPENDED, &dwThreadID); :SetThreadPriority(h2, THREAD_PRIORITY_IDLE); :ResumeThread(h2); / 等待两个线程内核对象都变成受信状态 :WaitForMultipleObjects( 3, h, TRUE, INFINITE); :CloseHandle(h0); :CloseHandle(h1); :CloseHandle(h2); return 0;二:在MFC下实现线程同步实例(含四种方法)这是一个基于单个文档的MFC程序(参考的是某本书
12、上完整的一个实例,所用代码和课件上几乎相同)操作步骤:1、新建“MFC APPWIZARD(EXE)”,选择文件路径,输入文件名2、选择应用程序类型为“单个文档”3、添加“线程同步的四种方法”的各菜单项,并在类向导的视类中添加各菜单消息函数ID号标题消息函数IDC_SYN_CRITICALSECTION临界区OnSynCriticalsectionIDC_SYN_EVENT事件内核对象OnSynEventIDC_SYN_MUTEX互斥内核对象OnSynMutexIDC_SYN_SEMAPHORE信号量内核对象OnSynSemaphore添加菜单消息响应函数的方法为:在MFC ClassWiza
13、rd(类向导)中的CMyView视图下选中要添加消息响应函数的菜单的ID号,单击右侧的Message中双击COMMAND,跳出函数名,单击OK即可 4、在“实现线程同步的四种方法View.cpp”文件开头添加头文件#include afxmt.h5、用“临界区”实现线程同步,在“实现线程同步的四种方法View.cpp”文件中添加相应代码1)编写线程函数char cArray10; /共享资源CCriticalSection criticalSection;/ MFC临界区类对象/临界区线程函数UINT ThreadCriticalFunc1(LPVOID param) / 进入临界区 crit
14、icalSection.Lock(); / 对共享资源进行写入操作 for (int i = 0; i 10; i+) cArrayi = a; Sleep(1); / 离开临界区 criticalSection.Unlock(); return 0; UINT ThreadCriticalFunc2(LPVOID param) / 进入临界区 criticalSection.Lock(); / 对共享资源进行写入操作 for (int i = 0; i 10; i+) cArray10 - i - 1 = b; Sleep(1); / 离开临界区 criticalSection.Unlock
15、(); return 0; 2)在类视图中选择OnSynCriticalsection(),添加代码void CMyView:OnSynCriticalsection() /临界区 / TODO: Add your command handler code here / TODO: Add your command handler code here / 启动线程 AfxBeginThread(ThreadCriticalFunc1, NULL); AfxBeginThread(ThreadCriticalFunc2, NULL); / 等待计算完毕 Sleep(300); / 报告计算结果
16、CString sResult = CString(cArray); AfxMessageBox(sResult); 3)运行程序,单击“临界区”弹出6、用“事件内核对象”实现线程同步,在“实现线程同步的四种方法View.cpp”文件中添加相应代码1)编写线程函数/ 事件内核对象CEvent event;UINT ThreadEventFunc1(LPVOID param) / 对共享资源进行写入操作 for (int i = 0; i 10; i+) cArrayi = a; Sleep(1); / 设置事件置位 event.SetEvent(); return 0; UINT Thread
17、EventFunc2(LPVOID param) / 等待事件 event.Lock(); / 对共享资源进行写入操作 for (int i = 0; i 10; i+) cArray10 - i - 1 = b; Sleep(1); return 0; 2)在类视图中选择OnSynEvent (),添加代码void CMyView:OnSynEvent() /事件内核对象 / TODO: Add your command handler code here / TODO: Add your command handler code here / 启动线程 AfxBeginThread(Thr
18、eadEventFunc1, NULL); AfxBeginThread(ThreadEventFunc2, NULL); / 等待计算完毕 Sleep(300); / 报告计算结果 CString sResult = CString(cArray); AfxMessageBox(sResult); 3)运行程序,单击“事件内核对象”,弹出7、用“互斥内核对象”实现线程同步,在“实现线程同步的四种方法View.cpp”文件中添加相应代码1)编写线程函数/互斥 CMutex mutex(FALSE, NULL); /互斥类对象 UINT ThreadMutexFunc1(LPVOID param
19、) mutex.Lock();/ 等待互斥对象通知 / 对共享资源进行写入操作 for (int i = 0; i 10; i+) cArrayi = a; Sleep(1); mutex.Unlock();/ 释放互斥对象 return 0; UINT ThreadMutexFunc2(LPVOID param) mutex.Lock();/ 等待互斥对象通知 / 对共享资源进行写入操作 for (int i = 0; i 10; i+) cArray10 - i - 1 = b; Sleep(1); mutex.Unlock();/ 释放互斥对象 return 0; 2)在类视图中选择On
20、SynMutex (),添加代码void CMyView:OnSynMutex() /互斥内核对象 / TODO: Add your command handler code here / TODO: Add your command handler code here / 启动线程 AfxBeginThread(ThreadMutexFunc1, NULL); AfxBeginThread(ThreadMutexFunc2, NULL); / 等待计算完毕 Sleep(300); / 报告计算结果 CString sResult = CString(cArray); AfxMessageBo
21、x(sResult); 3)运行程序,单击“互斥内核对象”,弹出 8、用“信号量内核对象”实现线程同步,在“实现线程同步的四种方法View.cpp”文件中添加相应代码(这个最符合当时老师布置的作业的要求)1)编写线程函数/信号量 CSemaphore semaphore(2, 2);/ 信号量类对象 UINT ThreadSemaphoreFunc1(LPVOID param) semaphore.Lock();/ 试图进入信号量关口 AfxMessageBox(线程一正在执行!);/ 线程任务处理 semaphore.Unlock();/ 释放信号量计数 return 0; UINT Thr
22、eadSemaphoreFunc2(LPVOID param) semaphore.Lock();/ 试图进入信号量关口 AfxMessageBox(线程二正在执行!); / 线程任务处理 semaphore.Unlock(); / 释放信号量计数 return 0; UINT ThreadSemaphoreFunc3(LPVOID param) semaphore.Lock();/ 试图进入信号量关口 AfxMessageBox(线程三正在执行!); / 线程任务处理 semaphore.Unlock(); / 释放信号量计数 return 0; 2)在类视图中选择OnSynSemaphor
23、e (),添加代码void CMyView:OnSynSemaphore() /信号量内核对象 / TODO: Add your command handler code here / TODO: Add your command handler code here / 启动线程 AfxBeginThread(ThreadSemaphoreFunc1, NULL); AfxBeginThread(ThreadSemaphoreFunc2, NULL); AfxBeginThread(ThreadSemaphoreFunc3, NULL); 3)运行程序,单击“信号量内核对象”,弹出单击其中一个对话框的“确定”,弹出
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1