}
getchar();
return0;
}
步骤1:
编译并执行3-1.exe程序。
程序运行结果是(分行书写):
①__________________________________________________________________
②__________________________________________________________________
③__________________________________________________________________
④__________________________________________________________________
⑤__________________________________________________________________
⑥__________________________________________________________________
阅读和分析程序3-1,请回答:
(1)程序中,创建一个信号量使用了哪一个系统函数?
创建时设置的信号量初始值是多少,最大值是多少?
a.__________________________________________________________________
b.__________________________________________________________________
(2)创建一个进程(子进程)使用了哪一个系统函数?
____________________________________________________________________
(3)从步骤1的输出结果,对照分析3-1程序,能够看出程序运行的流程吗?
请简单描述:
________________________________________________________________________
________________________________________________________________________
________________________________________________________________________
________________________________________________________________________
________________________________________________________________________
________________________________________________________________________
步骤2:
编译程序生成执行文件3-1.exe,在命令行状态下执行程序,分别使用格式:
(1)3-1child
(2)3-1或3-1***
运行程序,记录执行的结果,并分行说明产生不同结果的原因。
2.互斥量Mutex对象
注意:
多线程编程需要在VisualC++中设定多线程C运行时库。
打开你的工程项目后,在VisualC++的“Project”菜单下面,选择“Settings”菜单,如下两图所示,可以分别设定Debug版本和Release版本所使用的多线程C运行时库,以Debug开头的都是为Debug版本准备的,都选Multithread版本。
如果使用标准C库而调用VC运行时库函数,则在程序的link阶段会提示如下错误:
errorLNK2001:
unresolvedexternalsymbol__endthreadex
errorLNK2001:
unresolvedexternalsymbol__beginthreadex
清单3-2的程序中是读者写者问题的一个实现,满足读者优先原则,使用同步机制的互斥量实现,对每个读者和写者分别用一个线程来表示。
测试数据文件的数据格式说明:
测试数据文件包括n行测试数据,每行描述创建的是用于产生读者还是写者的数据。
每行测试数据包括4个字段,各字段间用空格分隔。
●第一字段为线程序号。
●第二字段表示相应线程角色,W表示写者,R表示读者。
●第三字段为线程延迟。
●第四字段为线程读写操作持续时间。
清单3-2利用互斥量Mutex实现读者写者问题
#include"windows.h"
#include"process.h"
#include
#include
#include
#include
#include
#include
#defineREADER'R'//读者
#defineWRITER'W'//写者
#defineINTE_PER_SEC1000//每秒时钟中断数目
#defineMAX_THREAD_NUM64//最大线程数目
#defineMAX_FILE_NUM32//最大数据文件数目
#defineMAX_STR_LEN32//字符串长度
volatileintreadcount=0;//读者数目
HANDLERP_Write;
structThreadInfo//定义线程数据结构
{
intserial;//线程序号
charentity;//线程类别(判断是读者线程还是写者线程)
doubledelay;//线程延迟
doublepersist;//线程读写操作持续时间
};
////////////////////////////////////////////////////////////////////////
///读者优先——读者线程
///p:
读者线程信息
unsignedint__stdcallRP_ReaderThread(void*p)
{
//互斥变量
HANDLEh_Mutex;
h_Mutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex_for_readcount");
DWORDwait_for_mutex;//等待互斥变量所有权
DWORDm_delay;//延迟时间
DWORDm_persist;//读文件持续时间
intm_serial;//线程序号
//从参数中获得信息
m_serial=((ThreadInfo*)(p))->serial;
m_delay=(DWORD)(((ThreadInfo*)(p))->delay*INTE_PER_SEC);
m_persist=(DWORD)(((ThreadInfo*)(p))->persist*INTE_PER_SEC);
Sleep(m_delay);//延迟等待
printf("Readerthread%dsentsthereadingrequire......\n",m_serial);
//等待互斥信号,保证对readcount的访问、修改互斥
wait_for_mutex=WaitForSingleObject(h_Mutex,-1);
//读者数目增加
readcount++;
if(readcount==1)
{//这是第一个读者,第二个读者到来时,readcount为2,if的条件不满足,不会进入if语句内部执行
//这是第一个读者,如果此刻没有写者正在写,则RP_Write信号量状态为可用(未占用),那它就必须先占用(锁定)RP_Write信号量,这就实现了读-写互斥
//如果此刻有写者正在写,则RP_Write信号量被写者占用(锁定),读者想对RP_Write加锁就会阻塞在此,等待RP_Write信号量释放后,才能继续运行
WaitForSingleObject(RP_Write,INFINITE);
}
ReleaseMutex(h_Mutex);//释放互斥信号
//读文件
printf("Readerthread%dbeginstoreadfile.\n",m_serial);
Sleep(m_persist);
//退出线程
printf("Readerthread%dfinishedreadingfile.\n",m_serial);
//等待互斥信号,保证对readcount的访问、修改互斥
wait_for_mutex=WaitForSingleObject(h_Mutex,-1);
//读者数目减少
readcount--;
if(readcount==0)
{
//如果所有读者读完,则释放RP_Write信号量;此刻若有写者正在等待(处于阻塞状态),将(自动)唤醒写者
ReleaseMutex(RP_Write);
}
ReleaseMutex(h_Mutex);//释放互斥信号
return0;
}
////////////////////////////////////////////////////////////////////////
//读者优先——写者线程
//p:
写者线程信息
unsignedint__stdcallRP_WriterThread(void*p)
{
DWORDm_delay;//延迟时间
DWORDm_persist;//写文件持续时间
intm_serial;//线程序号
//从参数中获得信息
m_serial=((ThreadInfo*)(p))->serial;
m_delay=(DWORD)(((ThreadInfo*)(p))->delay*INTE_PER_SEC);
m_persist=(DWORD)(((ThreadInfo*)(p))->persist*INTE_PER_SEC);
Sleep(m_delay);//延迟等待
printf("Writerthread%dsentsthewritingrequire.\n",m_serial);
//写者在进行写数据之前,必须确定没有其它写者正在写,也没有其它读者在读,
//通过RP_Write互斥量实现,若有其它写者正在写或其它读者在读,则该写者调用“WaitForSingleObject(RP_Write,INFINITE);”后将阻塞在此
//等待RP_Write信号量释放后,才能够继续向下执行。
WaitForSingleObject(RP_Write,INFINITE);
//写文件
printf("Writerthread%dbeginstowritetothefile.\n",m_serial);
Sleep(m_persist);
//退出线程
printf("Writerthread%dfinishedwritingtothefile.\n",m_serial);
//写者写完后,需要释放RP_Write信号量资源
ReleaseMutex(RP_Write);
return0;
}
///////////////////////////////////////////////////////////
//读者优先处理函数
//file:
文件名
voidReaderPriority(char*file)
{
inti;
DWORDn_thread=0;//线程数目
UINTthread_ID;//线程ID
DWORDwait_for_all;//等待所有线程结束
//互斥对象
HANDLEh_Mutex;
h_Mutex=CreateMutex(NULL,F