《实验二-进程(线程)的同步与互斥(7页).doc》由会员分享,可在线阅读,更多相关《实验二-进程(线程)的同步与互斥(7页).doc(7页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、-第 1 页实验二-进程(线程)的同步与互斥-第 2 页实验二 进程(线程)的同步与互斥一、实验目的1 掌握基本的同步与互斥算法,理解生产者消费者模型。2 学习使用 Windows 中基本的同步对象,掌握相关 API 的使用方法。3 了解 Windows 中多线程的并发执行机制,实现进程的同步与互斥。二、实验内容1 实验内容以生产者/消费者模型为依据,在 Windows 环境下创建一个控制台进程,在该进程中创建 n 个线程模拟生产者和消费者,实现进程(线程)的同步与互斥。Buffer(共享内存)生产者消费者2 实验要求 学习并理解生产者/消费者模型及其同步/互斥规则;学习了解 Windows
2、同步对象及其特性;熟悉实验环境,掌握相关 API 的使用方法;设计程序,实现生产者/消费者进程(线程)的同步与互斥;三、相关 API 的功能及使用我们利用 Windows SDK 提供的 API 编程实现实验题目要求,而 VC 中包含有 WindowsSDK 的所有工具和定义。要使用这些 API,需要包含堆这些函数进行说明的 SDK 头文件最常见的是 Windows.h(特殊的 API 调用还需要包含其他头文件)。下面给出的是本实验使用到的 API 的功能和使用方法简单介绍。(1)CreateThread 功能创建一个在调用进程的地址空间中执行的线程 格式HANDLE CreateThread
3、(LPSECURITY_ATTRIBUTES lpThreadAttributes,DWORD dwStackSize,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParamiter,DWORD dwCreationFlags,Lpdword lpThread);参数说明-第 3 页lpThreadAttributes指向一个 LPSECURITY_ATTRIBUTES(新线程的安全性描述符)。dwStackSize定义原始堆栈大小。lpStartAddress指向使用 LPTHRAED_START_ROUTINE 类型定义的函数。lpPara
4、miter定义一个给进程传递参数的指针。dwCreationFlags定义控制线程创建的附加标志。lpThread保存线程标志符(32 位)(2)CreateMutex 功能创建一个命名或匿名的互斥量对象 格式HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes,BOOL bInitialOwner,LPCTSTR lpName);参数说明lpMutexAttributes必须取值 NULL。bInitialOwner指示当前线程是否马上拥有该互斥量(即马上加锁)。lpName互斥量名称。(3)CreateSemaphore 功能
5、创建一个命名或匿名的信号量对象 格式HANDLE CreateSemaphore(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,LONG lInitialCount,LONG lMaximumCount,LPCTSTR lpName);参数说明lpSemaphoreAttributes必须取值 NULL。lInitialCount信号量的初始值。该值大于等于 0,但小于等于 lMaximumCount 指定的最大值。lMaximumCount信号量的最大值。lpName信号量名称。(4)WaitForSingleObject 功能使程序处于等待状态,直
6、到信号量 hHandle 出现(即其值大于 0)或超过规定的等待时间 格式DWORD WaitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds);参数说明hHandle信号量指针。dwMilliseconds等待的最长时间(INFINITE 为无限等待)。(5)ReleaseSemaphore 功能对指定信号量加上一个指定大小的量。成功执行则返回非 0 值 格式-第 4 页BOOL ReleaseSemaphore(HANDLE hSemaphore,LONG lReleaseCount,LPLONG lppreviousCount);参数
7、说明hSemaphore信号量指针。lReleaseCount信号量的增量。lppreviousCount保存信号量当前值。(6)ReleaseMutex 功能打开互斥锁,即把互斥量加 1。成功调用则返回 0 格式BOOL ReleaseMutex(HANDLE hMutex);参数说明hMutex互斥量指针。四、示例程序/定义一个结构体用于存储线程的信息struct ThreadInfoint serial;/线程号char entity;/线程类别(生产者或消费者)double delay;/等待时间double persist;/操作时间/生产者void Producer(void*p)
8、/定义变量用于存储当前线程的信息DWORD m_delay;DWORD m_persist;int m_serial;/从参数中获得信息m_serial=(ThreadInfo*)(p)-serial;m_delay=(DWORD)(ThreadInfo*)(p)-delay*INTE_PER_SEC);m_persist=(DWORD)(ThreadInfo*)(p)-persist*INTE_PER_SEC);while(running)/P 操作cout生产者线程 m_serial 请求生产.endl;WaitForSingleObject(g_hEmptySemaphore,INFIN
9、ITE);cout生产者线程 m_serial 请求独占缓冲区.endl;WaitForSingleObject(g_hMutex,INFINITE);Sleep(m_delay);/延迟等待/生产一个产品cout生产者线程m_serial 生产+ProductID 号产品成功.endl;-第 5 页cout生产者线程m_serial 请求将产品ProductID 投入缓冲区.endl;/把新生产的产品放入缓冲区g_bufferin=ProductID;in=(in+1)%SIZE_OF_BUFFER;Sleep(m_persist);/操作等待cout生产者线程 m_serial 将产品 P
10、roductID 投入缓冲区中成功.endl;/输出缓冲区当前的状态cout*endln 当前缓冲区情况如图(代表已有产品,代表没有产品):endl;for(int i=0;i0)cout;else cout;coutnn*nserial;m_delay=(DWORD)(ThreadInfo*)(p)-delay*INTE_PER_SEC);m_persist=(DWORD)(ThreadInfo*)(p)-persist*INTE_PER_SEC);while(running)/P 操作cout消费者线程 m_serial 请求消费.endl;WaitForSingleObject(g_hF
11、ullSemaphore,INFINITE);cout消费者线程 m_serial 请求独占缓冲区.endl;WaitForSingleObject(g_hMutex,INFINITE);Sleep(m_delay);/延迟等待/从缓冲区中取出一个产品cout消费者线程 m_serial 请求取出一个产品.endl;ConsumeID=g_bufferout;g_bufferout=0;out=(out+1)%SIZE_OF_BUFFER;cout消费者线程 m_serial 取出产品 ConsumeID 成功.endl;-第 6 页/消耗一个产品cout 消 费 者 线 程m_serial开
12、 始 消 费 消 费 产 品ConsumeID.endl;Sleep(m_persist);cout消费者线程 m_serial 消费产品 ConsumeID 成功.endl;/输出缓冲区当前的状态cout*endln 当前缓冲区情况如图:endl;for(int i=0;i0)cout;else cout;coutnn*nendl;/V 操作ReleaseMutex(g_hMutex);ReleaseSemaphore(g_hEmptySemaphore,1,NULL);五、实验结果六、实验结果分析1、记录生产者和消费者的同步执行过程2、分析 Producer 函数和 Consumer 函数
13、的功能,并画出对应的程序流程图。Producer 函数:通过用变量提取保存提取当前资源信息,然后判断是否执行,接着发出生产请求,请求通过后独占缓冲区资源,接着生产一个产品投入缓冲区,成功后释放所占缓冲区资源,到此此函数执行完成。Consumer 函数:也是通过用变量提取保存提取当前资源信息,然后判断是否执行,接着发出消费请求,请求通过后独占缓冲区资源,接着消费一个产品取出缓冲区,成功后释放所占缓冲区资源,到此此函数执行完成。线程号线程号线程类别线程类别延迟时间延迟时间操作时间操作时间操作请求操作请求缓冲区请求缓冲区请求生产(消费)结果生产(消费)结果1P12请求生产请求独占(在 2 前)生产成功2P26请求生产请求独占未生产3C45请求消费无未消费4C56请求消费无未消费5C32无无未消费-第 7 页Producer 函数:Consumer 函数:3、试将同步和互斥的 P 操作颠倒次序执行,观察并分析程序的运行情况。答:程序产生死锁。程序无法正常运行下去,因为同步和互斥的 P 操作颠倒次序,即先独占缓冲区资源,后发送请求,因为先独占缓冲区资源,若生产(消费)请求无法通过则一直等待,无法释放资源,因而程序死锁,无法运行了。
限制150内