VC60做的实现线程同步的四种方法的详细操作步骤.docx
《VC60做的实现线程同步的四种方法的详细操作步骤.docx》由会员分享,可在线阅读,更多相关《VC60做的实现线程同步的四种方法的详细操作步骤.docx(14页珍藏版)》请在冰豆网上搜索。
![VC60做的实现线程同步的四种方法的详细操作步骤.docx](https://file1.bdocx.com/fileroot1/2023-1/24/02115bde-0172-4a04-a79b-ba7665f4c20f/02115bde-0172-4a04-a79b-ba7665f4c20f1.gif)
VC60做的实现线程同步的四种方法的详细操作步骤
VC6.0做的实现线程同步的四种方法的详细操作步骤
软件作业一:
如何实现线程同步?
(二是一个基于单个文档的MFC程序,参考的是某本书上完整的一个可运行实例,所用代码和课件上几乎相同,应该会更符合老师上课讲的思路)
windows系统提供的4种同步化机制分别为:
临界区
信号量内核对象
事件内核对象
互斥体对象
一:
非MFC下实现线程同步实例
●临界区:
课本P43、44
//CriticalSection.cpp文件
#include
#include
#include
BOOLg_bContinue=TRUE;
intg_nCount1=0;
intg_nCount2=0;
CRITICAL_SECTIONg_cs;//对存在同步问题的代码段使用临界区对象
UINT__stdcallThreadFunc(LPVOID);
intmain(intargc,char*argv[])
{
UINTuId;
HANDLEh[2];
//初始化临界区对象
:
:
InitializeCriticalSection(&g_cs);
h[0]=(HANDLE):
:
_beginthreadex(NULL,0,ThreadFunc,NULL,0,&uId);
h[1]=(HANDLE):
:
_beginthreadex(NULL,0,ThreadFunc,NULL,0,&uId);
//等待1秒后通知两个计数线程结束,关闭句柄
Sleep(1000);
g_bContinue=FALSE;
:
:
WaitForMultipleObjects(2,h,TRUE,INFINITE);
:
:
CloseHandle(h[0]);
:
:
CloseHandle(h[1]);
//删除临界区对象
:
:
DeleteCriticalSection(&g_cs);
printf("g_nCount1=%d\n",g_nCount1);
printf("g_nCount2=%d\n",g_nCount2);
return0;
}
UINT__stdcallThreadFunc(LPVOID)
{
while(g_bContinue)
{
:
:
EnterCriticalSection(&g_cs);
g_nCount1++;
g_nCount2++;
:
:
LeaveCriticalSection(&g_cs);
}
return0;
}
●事件内核对象:
课本P46
//EventDemo.cpp文件
#include
#include
#include
HANDLEg_hEvent;
UINT__stdcallChildFunc(LPVOID);
intmain(intargc,char*argv[])
{
HANDLEhChildThread;
UINTuId;
//创建一个自动重置的(auto-resetevents),未受信的(nonsignaled)事件内核对象
g_hEvent=:
:
CreateEvent(NULL,FALSE,FALSE,NULL);
hChildThread=(HANDLE):
:
_beginthreadex(NULL,0,ChildFunc,NULL,0,&uId);
//通知子线程开始工作
printf("PleaseinputachartotelltheChildThreadtowork:
\n");
getchar();
:
:
SetEvent(g_hEvent);
//等待子线程完成工作,释放资源
:
:
WaitForSingleObject(hChildThread,INFINITE);
printf("Alltheworkhasbeenfinished.\n");
:
:
CloseHandle(hChildThread);
:
:
CloseHandle(g_hEvent);
return0;
}
UINT__stdcallChildFunc(LPVOID)
{
:
:
WaitForSingleObject(g_hEvent,INFINITE);
printf("Childthreadisworking......\n");
:
:
Sleep(5*1000);//暂停5秒,模拟真正的工作
return0;
}
●设定优先级实现三个线程的同步(参见课本P38)
///////////////////////////////////////////////////////////////
//PriorityDemo.cpp文件
#include
#include
HANDLEhMutex=NULL;
charg_cArray[10];
DWORDWINAPIThreadProc1(LPVOIDlpParam)
{
WaitForSingleObject(hMutex,INFINITE);
for(inti=0;i<10;i++)
{
g_cArray[i]='a';
printf("ThreadProc1NormalThreadisrunning\n");
printf("g_cArray[%d]=%c\n",i,g_cArray[i]);
Sleep(1000);//sleep
(1)约为15ms
}
ReleaseMutex(hMutex);
return0;
}
DWORDWINAPIThreadProc2(LPVOIDlpParam)
{
WaitForSingleObject(hMutex,INFINITE);
for(inti=0;i<10;i++)
{
g_cArray[10-i-1]='b';
printf("ThreadProc2LowestThreadisrunning\n");
printf("g_cArray[%d]=%c\n",10-i-1,g_cArray[10-i-1]);
Sleep(1000);
}
ReleaseMutex(hMutex);
return0;
}
DWORDWINAPIThreadProc3(LPVOIDlpParam)
{
WaitForSingleObject(hMutex,INFINITE);
for(inti=0;i<10;i++)
{
g_cArray[i]='c';
printf("ThreadProc3IdleThreadisrunning\n");
printf("g_cArray[%d]=%c\n",i,g_cArray[i]);
Sleep(1000);
}
ReleaseMutex(hMutex);
return0;
}
intmain(intargc,char*argv[])
{
DWORDdwThreadID;
HANDLEh[3];
//创建一个优先级为Normal的线程
h[0]=:
:
CreateThread(NULL,0,ThreadProc1,NULL,
0,&dwThreadID);
//创建一个优先级为Lowest的线程
h[1]=:
:
CreateThread(NULL,0,ThreadProc2,NULL,
CREATE_SUSPENDED,&dwThreadID);
:
:
SetThreadPriority(h[1],THREAD_PRIORITY_LOWEST);
:
:
ResumeThread(h[1]);
//创建一个优先级为Idle的线程
h[2]=:
:
CreateThread(NULL,0,ThreadProc3,NULL,
CREATE_SUSPENDED,&dwThreadID);
:
:
SetThreadPriority(h[2],THREAD_PRIORITY_IDLE);
:
:
ResumeThread(h[2]);
//等待两个线程内核对象都变成受信状态
:
:
WaitForMultipleObjects(
3,
h,
TRUE,
INFINITE);
:
:
CloseHandle(h[0]);
:
:
CloseHandle(h[1]);
:
:
CloseHandle(h[2]);
return0;
}
二:
在MFC下实现线程同步实例(含四种方法)
这是一个基于单个文档的MFC程序(参考的是某本书上完整的一个实例,所用代码和课件上几乎相同)
操作步骤:
1、新建“MFCAPPWIZARD(EXE)”,选择文件路径,输入文件名
2、选择应用程序类型为“单个文档”
3、添加“线程同步的四种方法”的各菜单项,并在类向导的视类中添加各菜单消息函数
ID号
标题
消息函数
IDC_SYN_CRITICALSECTION
临界区
OnSynCriticalsection
IDC_SYN_EVENT
事件内核对象
OnSynEvent
IDC_SYN_MUTEX
互斥内核对象
OnSynMutex
IDC_SYN_SEMAPHORE
信号量内核对象
OnSynSemaphore
添加菜单消息响应函数的方法为:
在MFCClassWizard(类向导)中的CMyView视图下选中要添加消息响应函数的菜单的ID号,单击右侧的Message中双击COMMAND,跳出函数名,单击OK即可
4、在“实现线程同步的四种方法View.cpp”文件开头添加头文件#include"afxmt.h"
5、用“临界区”实现线程同步,在“实现线程同步的四种方法View.cpp”文件中添加相应代码
1)编写线程函数
charcArray[10];//共享资源
CCriticalSectioncriticalSection;//MFC临界区类对象
//临界区线程函数
UINTThreadCriticalFunc1(LPVOIDparam)
{
//进入临界区
criticalSection.Lock();
//对共享资源进行写入操作
for(inti=0;i<10;i++)
{
cArray[i]='a';
Sleep
(1);
}
//离开临界区
criticalSection.Unlock();
return0;
}
UINTThreadCriticalFunc2(LPVOIDparam)
{
//进入临界区
criticalSection.Lock();
//对共享资源进行写入操作
for(inti=0;i<10;i++)
{
cArray[10-i-1]='b';
Sleep
(1);
}
//离开临界区
criticalSection.Unlock();
return0;
}
2)在类视图中选择OnSynCriticalsection(),添加代码
voidCMyView:
:
OnSynCriticalsection()//临界区
{
//TODO:
Addyourcommandhandlercodehere
//TODO:
Addyourcommandhandlercodehere
//启动线程
AfxBeginThread(ThreadCriticalFunc1,NULL);
AfxBeginThread(ThreadCriticalFunc2,NULL);
//等待计算完毕
Sleep(300);
//报告计算结果
CStringsResult=CString(cArray);
AfxMessageBox(sResult);
}
3)运行程序,单击“临界区”
弹出
6、用“事件内核对象”实现线程同步,在“实现线程同步的四种方法View.cpp”文件中添加相应代码
1)编写线程函数
//事件内核对象
CEventevent;
UINTThreadEventFunc1(LPVOIDparam)
{
//对共享资源进行写入操作
for(inti=0;i<10;i++)
{
cArray[i]='a';
Sleep
(1);
}
//设置事件置位
event.SetEvent();
return0;
}
UINTThreadEventFunc2(LPVOIDparam)
{
//等待事件
event.Lock();
//对共享资源进行写入操作
for(inti=0;i<10;i++)
{
cArray[10-i-1]='b';
Sleep
(1);
}
return0;
}
2)在类视图中选择OnSynEvent(),添加代码
voidCMyView:
:
OnSynEvent()//事件内核对象
{
//TODO:
Addyourcommandhandlercodehere
//TODO:
Addyourcommandhandlercodehere
//启动线程
AfxBeginThread(ThreadEventFunc1,NULL);
AfxBeginThread(ThreadEventFunc2,NULL);
//等待计算完毕
Sleep(300);
//报告计算结果
CStringsResult=CString(cArray);
AfxMessageBox(sResult);
}
3)运行程序,单击“事件内核对象”,弹出
7、用“互斥内核对象”实现线程同步,在“实现线程同步的四种方法View.cpp”文件中添加相应代码
1)编写线程函数
//互斥
CMutexmutex(FALSE,NULL);//互斥类对象
UINTThreadMutexFunc1(LPVOIDparam)
{
mutex.Lock();//等待互斥对象通知
//对共享资源进行写入操作
for(inti=0;i<10;i++)
{
cArray[i]='a';
Sleep
(1);
}
mutex.Unlock();//释放互斥对象
return0;
}
UINTThreadMutexFunc2(LPVOIDparam)
{
mutex.Lock();//等待互斥对象通知
//对共享资源进行写入操作
for(inti=0;i<10;i++)
{
cArray[10-i-1]='b';
Sleep
(1);
}
mutex.Unlock();//释放互斥对象
return0;
}
2)在类视图中选择OnSynMutex(),添加代码
voidCMyView:
:
OnSynMutex()//互斥内核对象
{
//TODO:
Addyourcommandhandlercodehere
//TODO:
Addyourcommandhandlercodehere
//启动线程
AfxBeginThread(ThreadMutexFunc1,NULL);
AfxBeginThread(ThreadMutexFunc2,NULL);
//等待计算完毕
Sleep(300);
//报告计算结果
CStringsResult=CString(cArray);
AfxMessageBox(sResult);
}
3)运行程序,单击“互斥内核对象”,弹出
8、用“信号量内核对象”实现线程同步,在“实现线程同步的四种方法View.cpp”文件中添加相应代码(这个最符合当时老师布置的作业的要求)
1)编写线程函数
//信号量
CSemaphoresemaphore(2,2);//信号量类对象
UINTThreadSemaphoreFunc1(LPVOIDparam)
{
semaphore.Lock();//试图进入信号量关口
AfxMessageBox("线程一正在执行!
");//线程任务处理
semaphore.Unlock();//释放信号量计数
return0;
}
UINTThreadSemaphoreFunc2(LPVOIDparam)
{
semaphore.Lock();//试图进入信号量关口
AfxMessageBox("线程二正在执行!
");//线程任务处理
semaphore.Unlock();//释放信号量计数
return0;
}
UINTThreadSemaphoreFunc3(LPVOIDparam)
{
semaphore.Lock();//试图进入信号量关口
AfxMessageBox("线程三正在执行!
");//线程任务处理
semaphore.Unlock();//释放信号量计数
return0;
}
2)在类视图中选择OnSynSemaphore(),添加代码
voidCMyView:
:
OnSynSemaphore()//信号量内核对象
{
//TODO:
Addyourcommandhandlercodehere
//TODO:
Addyourcommandhandlercodehere
//启动线程
AfxBeginThread(ThreadSemaphoreFunc1,NULL);
AfxBeginThread(ThreadSemaphoreFunc2,NULL);
AfxBeginThread(ThreadSemaphoreFunc3,NULL);
}
3)运行程序,单击“信号量内核对象”,弹出
单击其中一个对话框的“确定”,弹出