1、int Buffer_CriticalMAX_BUFFER_NUM; /缓冲区声明,用于存放产品(2)用自定义结构ThreadInfo记录一条线程信息,多个线程对应一个ThreadInfo数组。struct ThreadInfo int serial;/线程序列号 char entity;/是P还是C double delay;/线程延迟 int thread_requestMAX_THREAD_NUM;/线程请求队列 int n_request;/请求个数;(3)通过如下同步对象实现互斥:设一个互斥量h_mutex,实现生产者在查询和保留缓冲区的下一个空位置时进行互斥。HANDLE h_mu
2、tex;/一个互斥量设置h_SemaphoreMAX_THREAD_NUM信号量数组表示相应产品已经生产,实现生产者与消费者之间的同步。同时,用表示空缓冲区数目的信号量empty_semephore指示是否存在空位置,实现类似的同步,以便开始下一个产品的生产。/本程序允许的生产和消费线程的总数#define MAX_THREAD_NUM 64HANDLE h_SemaphoreMAX_THREAD_NUM;/生产者允许消费者开始消费的信号量设置临界区对象数组PC_CriticalMAX_BUFFER_NUM实现每个缓冲区上消费者之间的互斥。CRITICAL_SECTION PC_Critica
3、lMAX_BUFFER_NUM;/临界区对象的声明,用于管理缓冲区的互斥访问3.程序流程为了方便,程序结构用如下的文字予以描述。 (1) 主函数 (2) 初始化缓冲区、消费请求队列及部分同步对象 (3) 提取线程信息(到test.txt文件中提取) (4) 完成线程相关同步对象的初始化 (5) 创建线程,模拟生产者和消费者 (6) 等待所有线程结束 (7) 程序结束 (8) 消费者 (9) 有无消费请求?有,则继续(10);无,则转(16) (10) 此请求可满足?可满足,转(11);否,则阻塞,再转(10) (11) 确定产品位置 (12) 此产品正被消费?是,则阻塞,再转(12);否,则转
4、(13) (13) 进入临界区(请求同一产品的消费者之间互斥) (14) 消费产品,并判断是否应该释放产品所占缓冲区 (15) 退出临界区,转(9) (16) 结束消费者线程 (17) 生产者 (18) 存在空缓冲区?有,则继续(19);无,则阻塞,再转(18) (19) 另一生产者在写?否,则转(20);是,则阻塞,再转(19) (20) 进入临界区(请求同一产品的生产者之间互斥) (21) 在缓冲区中为本线程产品分配空间 (22) 退出临界区 (23) 写入产品到分配的缓冲区空间中 (24) 结束生产者线程4. 代码实现/ ThreadPC.cpp : 定义控制台应用程序的入口点#incl
5、ude stdafx.h#includefstreamstdio.hstringconio.hiostreamusing namespace std;/定义一些常量/秒到微秒的乘法因子#define INTE_PER_SEC 1000/定义一个结构,记录在测试文件中指定的每一个线程的参数 int serial; char entity; double delay; int thread_requestMAX_THREAD_NUM; int n_request;/全局变量的定义/struct _RTL_CRITICAL_SECTION;/typedef _RTL_CRITICAL_SECTION
6、 RTL_CRITICAL_SECTION;/typedef RTL_CRITICAL_SECTION CRITICAL_SECTION;HANDLE h_ThreadMAX_THREAD_NUM; /用于存储每个线程句柄的数组ThreadInfo Thread_InfoMAX_THREAD_NUM; /线程信息数组HANDLE empty_semaphore; /一个信号量 /一个互斥量DWORD n_Thread=0; /实际的线程的数目DWORD n_Buffer_or_Critical; /实际的缓冲区或者临界区的数目 /生产者允许消费者开始消费的信号量/生产消费及辅助函数的声明voi
7、d Produce(void*p);void Consume(void*p);bool IfInOtherRequest(int);int FindProducePosition();int FindBufferPosition(int);int main(void) /声明所需变量 int i = 0, j = 0; DWORD wait_for_all; ifstream inFile; /输入文件 /初始化缓冲区,即产品缓冲区,存储生产的产品,产品为正整数,-1表示空 for(int i=0;iMAX_BUFFER_NUM;i+) Buffer_Criticali=-1; /初始化每个线
8、程的请求队列 for(int j=0;jMAX_THREAD_NUM;j+) for(int k=0;kn_Buffer_or_Critical; /=3 inFile.get(); /读取n printf(输入文件是:n /回显获得的缓冲区的数目信息缓冲区的数目是:%dn,(int)n_Buffer_or_Critical); /提取每个线程的信息到相应数据结构中 while(inFile) inFileThread_Infon_Thread.serial; /线程号Thread_Infon_Thread.entity; /P生产者,C消费者Thread_Infon_Thread.delay
9、; /线程在生产和消费前的休眠时间,单位为秒 char c; inFile.get(c); while(c!=n&!inFile.eof() /c!说明delay列后面还有数据 inFile Thread_Infon_Thread.thread_requestThread_Infon_Thread.n_request+; inFile.get(c); n_Thread+; /输出获得的线程信息,便于确认正确性 cout从文件中获得的线程信息endl;serialtentitytdelaytrequestt. for(j=0;(int)n_Thread; int Temp_serial=Thre
10、ad_Infoj.serial; char Temp_entity=Thread_Infoj.entity; double Temp_delay=Thread_Infoj.delay; printf(n线程%2dt%ct%ft,Temp_serial,Temp_entity,Temp_delay); int Temp_request=Thread_Infoj.n_request;Temp_request; printf(%dt,Thread_Infoj.thread_requestk); coutserial; /本线程序号 m_delay = (DWORD)(ThreadInfo*)(p)-
11、delay*INTE_PER_SEC); /开始生产或消费之前的等待时间 Sleep(m_delay); /开始请求生产生产者%2d发送生产请求!,m_serial); /确认有空缓冲区可供生产,同时将控制访问空位置线程数目的信号量empty_semaphore的计数器减 wait_for_semaphore = WaitForSingleObject(empty_semaphore,-1); /等待互斥量,互斥访问下一个可用于生产的空临界区,实现写互斥 wait_for_mutex = WaitForSingleObject(h_mutex,-1); /生产者获取生产位置,有互斥量可保证不同
12、生产这可以找到不同的生产位置,同时信号量empty_semaphore可以保证生产者线程数不超过空位置数 int ProducePos = FindProducePosition(); /释放互斥量 ReleaseMutex(h_mutex); /生产者在获得自己的空位置并做上标记后,以下的写操作在生产者之间可以并发在核心生产步骤中,程序将生产者的ID作为产品编号放入,方便消费者识别生产者%2d开始在位置%2d上生产!, m_serial, ProducePos); /生产者生产中 Buffer_CriticalProducePos = m_serial;生产者%2d完成生产; ,m_seri
13、al);位置%2d:%3dn, ProducePos, Buffer_CriticalProducePos); /使生产者写的缓冲区可以被多个消费者使用,实现读写同步 ReleaseSemaphore(h_Semaphorem_serial,n_Thread,NULL);/消费者进程void Consume(void*p) DWORD wait_for_semaphore,m_delay; int m_serial,m_requestNum;/消费者的序列号和请求的数目 int m_thread_requestMAX_THREAD_NUM;/本消费线程的请求队列 /提取本线程的信息到本地 m_
14、serial=(ThreadInfo*)(p)- m_delay=(DWORD)(ThreadInfo*)(p)- m_requestNum=(ThreadInfo*)(p)-n_request;m_requestNum; m_thread_requesti=(ThreadInfo*)(p)-thread_requesti; /循环进行所需产品的消费 /请求消费下一个产品消费者%2d请求消费产品%2dn,m_serial,m_thread_requesti); /如果对应生产者没有生产,则等待; /如果生产了,允许的消费者数目为-1;实现了读写同步, /h_Semaphorem_thread_
15、requesti控制所请求的产品m_thread_requesti可以被多少个消费者线程使用 wait_for_semaphore = WaitForSingleObject(h_Semaphorem_thread_requesti,-1); /查询所需产品放到缓冲区的下标号 int BufferPos = FindBufferPosition(m_thread_requesti); /开始进行具体缓冲区的消费处理,读和读在该缓冲区上仍然是互斥的 /进入临界区后执行消费动作;并在完成此次请求后,通知另外的消费者本处请求已经满足; /同时如果对应的产品使用完毕,就做相应处理;并给出相应动作的界面
16、提示; /该相应处理指将相应缓冲区清空,并增加代表空缓冲区的信号量 /PC_CriticalBufferPos控制BufferPos位置的产品不同时被两个及两个以上的消费者线程消费 EnterCriticalSection(&PC_CriticalBufferPos);消费者%2d开始消费产品%2dn (ThreadInfo*)(p)-thread_requesti = -1; if(!IfInOtherRequest(m_thread_requesti) Buffer_CriticalBufferPos=-1;/标记缓冲区为空消费者%2d完成消费%2d:位置%2d:,BufferPos,Buffer_CriticalBufferPos); ReleaseSemaphore(empty_semaphore,1,NULL); else消费者%2d完成消费产品%2dn /离开临界区 LeaveCriticalSection(&
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1