os实验二 进程同步
- 格式:doc
- 大小:68.00 KB
- 文档页数:6
操作系统实验报告哈尔滨工程大学计算机科学与技术学院第六讲进程的同步一、实验概述1. 实验名称进程的同步2. 实验目的(1)使用EOS 的信号量编程解决生产者—消费者问题,理解进程同步的意义。
(2)调试跟踪EOS 的信号量的工作过程,理解进程同步的原理。
(3)修改EOS 的信号量算法,使之支持等待超时唤醒功能(有限等待),加深理解进程同步的原理。
3. 实验类型验证型实验,设计性实验4. 实验内容(1)准备实验(2)使用 EOS 的信号量解决生产者-消费者问题(3)调试 EOS 信号量的工作过程1)创建信号量2)等待释放信号量3)等待信号量(不阻塞)4)释放信号量(不唤醒)5) 等待信号量(阻塞)6) 释放信号量(唤醒)(4)修改 EOS 的信号量算法二、实验环境操作系统集成实验环境OS Lab三、实验过程1. 设计思路和流程图2. 算法实现3. 需要解决的问题及解答(1). P143生产者在生产了13号产品后本来要继续生产14号产品,可此时生产者为什么必须等待消费者消费了4号产品后,才能生产14号产品呢?生产者和消费者是怎样使用同步对象来实现该同步过程的呢?答:此时生产了0-13号14个产品,消费了0-3号4个产品,缓冲区都占满了。
只有缓冲区有空闲生产者才能生产东西,有权向里面放东西。
所以它必须等到消费者,取走产品,有空闲缓冲区时,才继续生产14号产品。
(2). P145-3.4 修改EOS的信号量算法(只看一次消费1个产品的,一次消费2个产品的可以写到实验报告中)答:见三,四部分(3). 思考在ps/semaphore.c文件内的PsWaitForSemaphore和PsReleaseSemaphore函数中,为什么要使用原子操作?答:原子操作要求一旦开始就要运行到结束,不能有中断。
在执行等待信号量和释放信号量的时候,不允许cpu响应外部中断,所以使用原子操作。
(4). 绘制ps/semaphore.c文件内PsWaitForSemaphore和PsReleaseSemaphore函数的流程图。
操作系统实验二实验报告一、实验目的本次操作系统实验二的主要目的是深入理解和掌握进程管理的相关概念和技术,包括进程的创建、执行、同步和通信。
通过实际编程和实验操作,提高对操作系统原理的认识,培养解决实际问题的能力。
二、实验环境本次实验使用的操作系统为 Windows 10,编程环境为 Visual Studio 2019。
三、实验内容及步骤(一)进程创建实验1、首先,创建一个新的 C++项目。
2、在项目中,使用 Windows API 函数`CreateProcess`来创建一个新的进程。
3、为新进程指定可执行文件的路径、命令行参数、进程属性等。
4、编写代码来等待新进程的结束,并获取其退出代码。
(二)进程同步实验1、设计一个生产者消费者问题的模型。
2、使用信号量来实现生产者和消费者进程之间的同步。
3、生产者进程不断生成数据并放入共享缓冲区,当缓冲区已满时等待。
4、消费者进程从共享缓冲区中取出数据进行处理,当缓冲区为空时等待。
(三)进程通信实验1、选择使用管道来实现进程之间的通信。
2、创建一个匿名管道,父进程和子进程分别读写管道的两端。
3、父进程向管道写入数据,子进程从管道读取数据并进行处理。
四、实验结果及分析(一)进程创建实验结果成功创建了新的进程,并能够获取到其退出代码。
通过观察进程的创建和执行过程,加深了对进程概念的理解。
(二)进程同步实验结果通过使用信号量,生产者和消费者进程能够正确地进行同步,避免了缓冲区的溢出和数据的丢失。
分析结果表明,信号量机制有效地解决了进程之间的资源竞争和协调问题。
(三)进程通信实验结果通过管道实现了父进程和子进程之间的数据通信。
数据能够准确地在进程之间传递,验证了管道通信的有效性。
五、遇到的问题及解决方法(一)在进程创建实验中,遇到了参数设置不正确导致进程创建失败的问题。
通过仔细查阅文档和调试,最终正确设置了参数,成功创建了进程。
(二)在进程同步实验中,出现了信号量使用不当导致死锁的情况。
OS实验指导一2013计算机科学与技术(师范)+2014信息管理与信息系统《操作系统》实验指导一开课实验室:A209 2015-9-14int Rmutex=1;//表示对Rcount的互斥操作int r[10]={0,0,0,0,0,0,0,0,0,0};//表示读者的状态,1表示正在读int w[10]={0,0,0,0,0,0,0,0,0,0};//表示写者的状态,1表示正在写int w_wait[11]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};//表示等待队列,0-9表示写者,10时需引入读者的等待队列,-1表示空int r_wait[11]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};//读者的等待队列,0-9表示对应的读者,-1为空5. 模块说明四组P、V函数:1)写者进程由3个函数组成void write_p(int i);//模拟写者对Wmutex的P操作,同时也作为写者进程的入口void write(int i);//开始写操作void write_v(int i);//模拟写者对Wmutex的V操作,写操作完成的时候调用2)读者进程由8个函数组成void radd_p(int i);//模拟读之前对Rmutex的P操作,同时也作为读者进程的入口void radd(int i);//Rcount加1void read_p(int i);//模拟读者对Wmutex的P操作void radd_v(int i);//模拟读之前对Rmutex的V操作void read(int i);//读void rsub_p(int i);//模拟读之后对Rmutex的P操作,读操作完成的时候调用void rsub(int i);//Rcount减1void read_v(int i);//模拟读者对Wmutex的V操作void rsub_v(int i);//模拟读之后对Rmutex的V操作源程序的主要部分1写操作的设计:模拟写者对Wmutex的P操作,同时为写者进程也作写的入口:void write_p(int i){Wmutex--;。
进程同步:实验报告1.实验内容(进程的同步)(1) 阅读理解⽰例程序。
(2) 说明⽰例程序是否能适合解决 N 个⽣产者和 1 个消费者问题,并设计实验验证(3) 参照教材修改为 N 个⽣产者和 1 个消费者问题(4) 思考 N 个⽣产者和 M 个消费者问题的解决⽅案(不要求)(5) 利⽤信号量解决同步问题。
2.实验⽬的通过程序模拟及验证⽣产者消费者问题等经典问题,深⼊理解并发中的同步和互斥的概念3.实验原理(1)进程概念:(1.定义:程序的⼀次执⾏过程( 2.三种基本状态 :就绪状态,执⾏状态,阻塞状态(2)进程同步:(1.定义:并发进程在执⾏次序上的协调,以达到有效的资源共享和相互合作,使程序执⾏有可再现性。
( 2.两种形式的制约关系: (⼀:资源共享关系:进程间接制约,需互斥地访问临界资源。
)、(⼆:相互合作关系:进程直接制约)(3.临界资源:⼀次仅允许⼀个进程访问的资源,引起不可再现性是因为临界资源没有互斥访问。
(3)信号量:定义⼀个⽤于表⽰资源数⽬的整型量S,它与⼀般的整型量不同,除初始化外,仅能通过两个标准的原⼦操作 wait(S)和 signal(S)来访问,俗称 P,V操作。
通俗来讲就是⽤P 来访问资源后减去⼀个单位资源,⽤ V 操作来释放⼀个单位资源就是现有资源上加⼀个单位资源。
4.实验内容⼀:说明⽰例程序是否能适合解决 N 个⽣产者和 1 个消费者问题,并设计实验验证答:⽰例程序不能解决多个⽣产者和消费者的问题,它是解决单个消费者和⽣产者的。
如果可以就要修改代码,如“⼆”所说。
⼆:多个消费者和⽣产者的问题⽣产者 1 如上图所⽰:如果要解决多个⽣产者和消费者的问题:第⼀步:分析上图得出了两种关系,分别是异步和同步的关系第⼆步:异步关系的是⽣产者和⽣产者之间的,因为同⼀时刻只能有⼀个⽣产者访问缓冲区,所以我们就可以设置临界资源 .获得临界资源的⽣产者才能把产品放到缓冲区⾥第三步:同步关系有两个,⾸先是⽣产者和缓冲区之间,再是缓冲区和消费者之间。
嵌入式实时操作系统实验报告1实验名称:uC/OS-II任务间通讯和同步实验姓名:班级:信科10-4班学号:uC/OS-II任务间通讯和同步实验一、实验目的1、掌握uC/OS-II操作系统下使用信号量解决任务之间的同步问题;2、掌握uC/OS-II操作系统下任务间通讯的方法。
二、实验内容1、使用信号量实现任务间同步(Eg2工程)2、使用邮箱实现任务之间的通讯(Eg3工程)三、基础知识uC/OS-II任务之间的通讯与同步方式1、利用宏OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()来关闭中断和打开中断2、利用函数OSSchedLock()和OSSchekUnlock()对µC/OS-II中的任务调度函数上锁和开锁3、信号量4、邮箱5、队列uC/OS-II中使用信号量进行任务之间同步1、通过调用OSSemCreate()建立信号量2、通过调用OSSemPost()函数发送一个信号量3、通过调用OSSemPend()函数等待一个信号量OSSemCreate1、Sem1 = OSSemCreate(0);2、参数为信号量的初始计数值赋值。
该初始值为0到65,535之间的一个数。
3、如果信号量是用来表示一个或者多个事件的发生,那么该信号量的初始值应设为0。
4、如果信号量是用于对共享资源的访问,那么该信号量的初始值应设为1(例如,把它当作二值信号量使用)。
5、如果该信号量是用来表示允许任务访问n个相同的资源,那么该初始值显然应该是n,并把该信号量作为一个可计数的信号量使用。
OSSemPost和OSSemPend1、如果信号量当前是可用的(信号量的计数值大于0),将信号量的计数值减1,然后函数将“无错”错误代码返回给它的调用函数。
如果信号量的计数值为0,而OSSemPend()函数又不是由中断服务子程序调用的,则调用OSSemPend()函数的任务要进入睡眠状态,等待另一个任务(或者中断服务子程序)发出该信号量。
XI`AN TECHNOLOGICAL UNIVERSITY 实验报告进程同步的多种解决办法摘要:简单介绍了进程同步的概念,分析了进程同步的多种解决办法,重点讨论了读者写者问题,更容易了解解决办法的具体机制。
关键词:进程同步;多进程;读者-写者0 引言Windows应用程序中消息有两种送出途径,直接和排队。
Windows或某些运行的应用程序可直接发布消息给窗口过程,或消息可送达到消息列象连续不断地轮询消息队列的OS中当前执行的每一个进程都不是由事件的顺序来控制的,而是由事件的发生来控制的。
在传统的操作系统中,为提高资源利用率和系统吞吐量,通常采用多道程序技术,将多个程序同时装入内存,并使之并发执行。
1 同步在OS中引入进程后,一方面使系统中多道程序并发执行,这不仅使资源利用率改善,亦可显著提高系统吞吐量,但也使系统更为复杂,致使进程对系统资源的无序争夺,每次处理的结果存在不确定性,显现不可再现性。
因此,在多道程序系统中,必须引入进程同步机制。
在本文中将介绍如下几种进程同步机制——硬件同步机制,信号量机制,管程机制和Peri网。
2 进程同步解决办法2.1 硬件同步机制目前许多计算机已提供特殊的硬件指令,允许对一个字中的内容进行检测和改正或对两个字进行交换。
可利用特殊指令解决临界的问题。
对临界区管理时,可将标志看作一个锁,“锁开”进入,“锁关”等待,初始状态锁是开着的。
但当临界资源忙碌时,其他进程处于“忙等”状态,不符合“让权等待”原则,造成处理机时间的浪费,同时很难解决,解决复杂的进程同步问题。
2.2 信号量机制信号量机制已得到广泛发展,由整形信号量经记录型信号量,发展到“信号量集机制”,已广泛应用于单处理机和多处理机系统以及计算机网络中。
信号量机制通常包括整型信号量,记录型信号量,AND型信号量和信号量集。
2.2.1 整型信号量除初始化外,仅能通过两个标准的原子操作wait(S)和signal(S)来访问。
《操作系统实验》
实验一:进程的同步和互斥
黄伯虎
实验内容
生产者消费者问题实现
描述:
假设存在两类进程:生产者,消费者。
它们共享n个缓冲区。
生产者行为:生产产品(每次生产1个),并将产品放入空缓冲区,循环往复,永不停息;
消费者行为:将产品从缓冲区中取出,进行消费(每次消费1个),循环往复,永不停息。
规定:缓冲区满,生产者不能放产品;缓冲区空,消费者不能取产品
要求
基本要求
实现当n=1,生产者、消费者各为1个时,同步和互斥过程
扩展要求(可选)
实现当n=c(整常数),生产者、消费者有多个(>1)时,同步和互斥过程平台和工具(原则不限,推荐如下)
Win32平台
VC++6.0
结果显示
字符界面,能说明问题即可
最终成果形式
提交实验报告1份(格式参见附件A)
报告提交时限:下一次实验开始前
提交形式:email
提交的邮件主题请按照如下格式书写:“学号+姓名+实验名称.rar/.doc”
如“030811300+张三+进程同步与互斥.rar/.doc”提交地址:
13班:xdos1@
14,31班:xdos2@。
0711操作系统进程调度和进程同步实验要求实验内容:用线程模拟进程,实现进程调度和进程同步。
在任意操作系统中,用c、c++或者java 编写程序。
并且完成相应的实验报告。
实验要求:实验一:进程调度⑴ 主线程,创建子线程,保存子线程的虚拟PCB(参见恐龙书P74)、要求运行多少时间(可随机产生)、已经等待多少时间(初始化为0),优先级(可随机产生)等信息,并负责子线程的调度。
调度的基本时间单位为1 S。
⑵ 创建20个线程(可以只用一个线程函数,传递不同的参数即上述数据结构)分别实现FCFS调度、SJF调度、RR调度、优先级调度和多级队列调度,并且计算每个调度的平均等待时间。
其中,多级队列调度要求设计4个调度队列,每个队列5个线程,队列内部分别采用FCFS、SJF、RR和优先级调度。
时间片的长度可以随机生成为n S。
⑶ 对于每个子线程,在其运行期间,输出其占用的时间标号(例如,第3个线程占用了第10秒的CPU时间,输出为:“Thread 3: 10”,格式可自行设计)。
实验二:进程同步⑴ 模拟哲学家就餐问题:设置5个子线程模拟5个哲学家,设置5个互斥区为筷子。
⑵ 输出问题解决方法:在每个哲学家线程中输出其获得的筷子标号与时间(可以读取系统时间,或者自行设置时间标准),例如:哲学家2在第n秒获得筷子1,在第m秒获得筷子2。
实验报告要求:写明实验目的、实验设计步骤、实验结果、总结。
附录:windows线程基本操作以windows线程函数为例介绍线程基本操作,以下函数都必须包含windows.h头文。
如果想更深入地了解线程,请参见《c++编程艺术》等相关书籍。
线程创建函数:HANDLE CreateThread (LPSECURITY_ATTRIBUTES secAttr,SIZE_T stackSize,LPTHREAD_START_ROUTINE threadFunc,LPVOID param,DWORD flags,LPDWORD threadID);在此,secAttr是一个用来描述线程的安全属性的指针。
}阅读、调试、运行、分析程序,写出运行结果,这个结果与你期望的一致吗?(从进程并发的角度对结果进行分析)思考题1.分析进程与线程创建及控制的异同。
(1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位(2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行(3)拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源.(4)系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。
2.分析线程各API函数的功能及使用方法。
线程创建函数:CreateThread()获得线程优先级函数:GetThreadPriority()设置线程优先级函数:SetThreadPriority()判断线程当前是否处于运行状态函数:GetExitCodeThread()获得线程标识符函数:GetCurrentThreadID()ResumeThread()用于挂起线程的函数:SuspendThread()终止线程函数:ExitThread()终止线程函数:TerminateThread()实验过程与结果:程序4_1两个线程无同步代码,观察 i 值。
#include <iostream.h>#include <windows.h>#define M 90000 // 循环次数要很大,可多次尝试一些值int i = 0;DWORD _stdcall fun1( LPVOID p1){ for( int j =0 ;j < M;j++) i++;return 0;}DWORD _stdcall fun2( LPVOID p1){ for( int j =0 ;j < M;j++) i--;return 0;}int main(){ DWORD id1,id2;HANDLE hThread[2];hThread[0] = CreateThread(0,0,fun1,0,0,&id1);hThread[1] = CreateThread(0,0,fun2,0,0,&id2);WaitForMultipleObjects(2, // 等待句柄的数量hThread, //句柄数组的指针1, //TRUE等待所有对象,FALSE第一个信号到来就向下执行INFINITE); //一直等待cout<<"i = "<<i<<endl;return 0;}InitializeCriticalSection(&cs);hThread[0] = CreateThread(0,0,fun1,0,0,&id1);hThread[1] = CreateThread(0,0,fun2,0,0,&id2);WaitForMultipleObjects(2,hThread,1,INFINITE);cout<<"i = "<<i<<endl;DeleteCriticalSection(&cs);return 0;}无论如何执行,i的值总是0,结果是正确的。
实验二:进程同步一.实验目的(1)掌握基本的同步算法,理解生产者消费者模型。
(2)学习使用Windows XP中基本的同步对象,掌握相关API的使用方法。
(3)了解Windows XP中多线程的并发执行机制,实现进程的同步与互斥。
二.实验属性该实验为设计性实验。
三.实验仪器设备及器材普通PC386以上微机四.实验要求本实验要求2学时完成。
本实验要求完成如下任务:1.以生产者/消费者模型为依据,在Windows XP环境下创建一个控制台进程,在该进程中创建n个线程模拟生产者和消费者,实现进程(线程)的同步与互斥。
1>学习并理解生产者/消费者模型及其同步/互斥规则;2>学习了解Windows同步对象及其特性;3>熟悉实验环境,掌握相关API的使用方法;4>设计程序,实现生产者/消费者进程(线程)的同步与互斥。
2.扩展任务2选1:1>利用信号量机制,写出不会发生死锁的解决哲学家进程(线程)。
最多允许4个同时进餐;奇:先左后右偶:先右后左。
2>利用信号量机制,写出不会发生死锁的读者写者进程(线程)。
五.相关知识介绍1.同步对象同步对象是指Windows中用于实现同步与互斥的实体,包括信号量(Semaphore)、互斥量(Mutex)、临界区(Critical Section)和事件(Events)等。
同步对象的使用步骤:●创建/初始化同步对象。
●请求同步对象,进入临界区(互斥量上锁)。
●释放同步对象(互斥量解锁)。
这些对象在一个线程中创建,在其他线程中都可以使用,实现同步与互斥。
2.相关API的功能及使用我们利用Windows SDK提供的API编程实现实验题目要求,而VC 中包含有Windows SDK的所有工具和定义。
要使用这些API,需要包含堆这些函数进行说明的SDK头文件——最常见的是Windows.h(特殊的API 调用还需要包含其他头文件)。
下面给出的是本实验使用到的API的功能和使用方法简单介绍。
实验一进程同步和互斥(建议4学时)一、实验目的1.掌握临界资源、临界区概念及并发进程互斥、同步访问原理。
2.学会使用高级语言进行多线程编程的方法。
3.掌握利用VC++或Java语言线程库实现线程的互斥、条件竞争,并编码实现P、V 操作,利用P、V操作实现两个并发线程对有界临界区的同步访问。
4.通过该实验,学生可在源代码级完成进程同步互斥方案的分析、功能设计、编程实现,控制进程间的同步、互斥关系。
二、实验要求1.知识基础:学生应在完成进程和线程及调度等章节的学习后进行。
2.开发环境与工具:硬件平台——个人计算机。
软件平台-Windows操作系统,vc++语言或Java语言开发环境。
3.运用高级语言VC++或Java语言线程库及多线程编程技术进行设计实现。
三、实验内容1.实现临界资源、临界区、进程或线程的定义与创建。
2.利用两个并发运行的进程,实现互斥算法和有界缓冲区同步算法。
四、实验方案指导该实验方案由以下几个关键设计项目组成:1.并发访问出错。
即设计一个共享资源,创建两个并发线程,二者并发访问该共享资源。
当没有采用同步算法设计时,线程所要完成的某些操作会丢失。
2.互斥锁。
并发线程使用线程库提供的互斥锁,对共享资源进行访问。
3.软件方法。
设计并编程实现计数信号量、P操作函数、V操作函数,并发线程通过调用P,V操作函数实现线程的互斥。
4.同步访问多缓冲区。
利用上面的软件方法完成P,V操作,可实现两个线程对多缓冲区的同步访问。
五、实验方案实现范例以下是对该项目中包含的部分设计功能的实现方法、实现过程、技术手段的描述,供师生参考。
1.模拟线程并发运行。
假设我们使用POSIX线程库,而POSIX并没有真正提供线程间的并发运行需求。
我们设计的系统应支持符合RR调度策略的并发线程,每个线程运行一段时间后自动挂起,另一个线程开始运行。
这样一个进程内所有线程以不确定的速度并发执行。
2.模拟一个竞争条件——全局变量。
进程通信(实验二)【实验目的】:掌握用邮箱方式进行进程通信的方法,并通过设计实现简单邮箱理解进程通信中的同步问题以及解决该问题的方法。
【实验原理】:邮箱机制类似于日常使用的信箱。
对于用户而言使用起来比较方便,用户只需使用send()向对方邮箱发邮件receive()从自己邮箱取邮件,send()和receive()的内部操作用户无需关心。
因为邮箱在内存中实现,其空间有大小限制。
其实send()和receive()的内部实现主要还是要解决生产者与消费者问题。
【实验内容】:进程通信的邮箱方式由操作系统提供形如send()和receive()的系统调用来支持,本实验要求学生首先查找资料了解所选用操作系统平台上用于进程通信的系统调用具体形式,然后使用该系统调用编写程序进行进程间的通信,要求程序运行结果可以直观地体现在界面上。
在此基础上查找所选用操作系统平台上支持信号量机制的系统调用具体形式,运用生产者与消费者模型设计实现一个简单的信箱,该信箱需要有创建、发信、收信、撤销等函数,至少能够支持两个进程互相交换信息,比较自己实现的信箱与操作系统本身提供的信箱,分析两者之间存在的异同。
实验背景介绍进程间通信有如下目的:数据的传输,共享数据,通知事情,资源共享,进程控制。
进程间的通信机制(IPC),就是多进程相互通信,交换信息的方法。
Linux IPC机制包括,信号和管道是其中的两个,还支持传统的UNIX SYSTM-V 的IPC 机制。
信号主要用来通知进程异步事情的发生,最初信号设计的目的是为了处理错误,他们也用来作为最基本的IPC机制。
管道是单向的,先进先出,先入先出,无结构的,固定大小的数据流。
UNIX System V 机制中的三种进程间通信机制,它们是:消息队列:用于进程之间传递分类的格式化数据信号量:用于通信之间的同步控制。
信号量通常与共享存储器方式一起使用。
共享内存:使不同进程通过共享彼此的虚拟空间而达到相互对共享区操作和数据通信。
操作系统进程同步20 年月日A4打印/ 可编辑进程调度和进程同步实验要求实验内容:用线程模拟进程,实现进程调度和进程同步。
在任意操作系统中,用c、c++或者java编写程序。
并且完成相应的实验报告。
实验要求:实验一:进程调度1.主线程,创建子线程,保存子线程的虚拟PCB(参见恐龙书P74)、要求运行多少时间(可随机产生)、已经等待多少时间(初始化为0),优先级(可随机产生)等信息,并负责子线程的调度。
调度的基本时间单位为1S。
2.创建20个线程(可以只用一个线程函数,传递不同的参数即上述数据结构)分别实现FCFS调度、SJF调度、RR调度、优先级调度和多级队列调度,并且计算每个调度的平均等待时间。
其中,多级队列调度要求设计4个调度队列,每个队列5个线程,队列内部分别采用FCFS、SJF、RR和优先级调度。
时间片的长度可以随机生成为nS。
3.对于每个子线程,在其运行期间,输出其占用的时间标号(例如,第3个线程占用了第10秒的CPU时间,输出为:“Thread3:10”,格式可自行设计)。
实验二:进程同步1.模拟哲学家就餐问题:设置5个子线程模拟5个哲学家,设置5个互斥区为筷子。
2.输出问题解决方法:在每个哲学家线程中输出其获得的筷子标号与时间(可以读取系统时间,或者自行设置时间标准),例如:哲学家2在第n 秒获得筷子1,在第m秒获得筷子2。
实验报告要求:写明实验目的、实验设计步骤、实验结果、总结。
附录:windows线程基本操作以windows线程函数为例介绍线程基本操作,以下函数都必须包含windows.h头文。
如果想更深入地了解线程,请参见《c++编程艺术》等相关书籍。
线程创建函数:HANDLECreateThread( LPSECURITY_ATTRIBUTES secAttr,SIZE_T stackSize,LPTHREAD_START_ROUTINE threadFunc,LPVOID param,DWORD flags,LPDWORD threadID);在此,secAttr是一个用来描述线程的安全属性的指针。
实验二:进程同步一.实验目的(1)掌握基本的同步算法,理解生产者消费者模型。
(2)学习使用Windows XP中基本的同步对象,掌握相关API的使用方法。
(3)了解Windows XP中多线程的并发执行机制,实现进程的同步与互斥。
二.实验属性该实验为设计性实验。
三.实验仪器设备及器材普通PC386以上微机四.实验要求本实验要求2学时完成。
本实验要求完成如下任务:(1)以生产者/消费者模型为依据,在Windows XP环境下创建一个控制台进程,在该进程中创建n个线程模拟生产者和消费者,实现进程(线程)的同步与互斥。
学习并理解生产者/消费者模型及其同步/互斥规则;学习了解Windows同步对象及其特性;熟悉实验环境,掌握相关API的使用方法;设计程序,实现生产者/消费者进程(线程)的同步与互斥。
(2)扩展任务2选1:1>利用信号量机制,写出不会发生死锁的解决哲学家进程(线程)。
最多允许4个同时进餐;奇:先左后右偶:先右后左。
2>利用信号量机制,写出不会发生死锁的读者写者进程(线程)。
五:实验内容:利用至多同时允许4位哲学家同时去拿左边筷子的方法解决进餐死锁的问题。
实验详细设计:流程图:程序首先创建一个线程参数结构体struct ThreadInfo{int serial;double delay;};设置最多同时去拿筷子的人数#define MAX_BUFFER_NUM 4设置一个信号量数组用来表示五位哲学家的左右边的筷子HANDLE chopstick [5];设置同时去拿筷子的人数的信号量HANDLE People;设置一个互斥信号量HANDLE h_mutex;在main()函数中,首先创建信号量:for (int i=0;i<5;i++){chopstick[i]=CreateSemaphore(NULL,n_Buffer_or_Critical,n_Buffer_or_Criti cal,"chopstick"+i);}People=CreateSemaphore(NULL,MAX_BUFFER_NUM,MAX_BUFFER _NUM,"People");h_mutex=CreateMutex(NULL,FALSE, "mutex_for_update");创建线程for (int j=0;j<(int)n_Thread;j++){h_Thread[j]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(eat),& (Thread_Info[j]),0,NULL);}线程执行函数:void eat(void*p){//局部变量声明DWORDwait_for_semaphore1,wait_for_semaphore2,wait_for_People,wait_for_mutex, m_delay;int m_serial;//获得本线程信息m_serial=((ThreadInfo*)(p))->serial;WaitForSingleObject(h_mutex,-1);WaitForSingleObject(People,-1);printf("哲学家%2d 开始准备拿筷子.\n",m_serial);wait_for_semaphore1=WaitForSingleObject(chopstick[m_serial],-1);wait_for_semaphore2=WaitForSingleObject(chopstick[(m_serial+1)%5],-1);ReleaseSemaphore(People,1,NULL);ReleaseMutex(h_mutex);Sleep(1000);printf("哲学家%2d 开始进餐.\n",m_serial);Sleep(1000);printf( "哲学家%2d 结束进餐.\n",m_serial);ReleaseSemaphore(chopstick[m_serial],1,NULL);ReleaseSemaphore(chopstick[(m_serial+1)%5],1,NULL);//ReleaseSemaphore(People,1,NULL);}六:实验结果调试七:实验总结:这次实验最主要的难点实在信号量的使用上,刚开始由于信号量使用的位置不是很正确,结果造成一些数据竞争,并且出现死锁的现象,后来经过仔细检查,最后终于正确的将各个信号量放在相应的位置,信号量的使用顺序为:WaitForSingleObject(h_mutex,-1);WaitForSingleObject(People,-1);WaitForSingleObject(chopstick[m_serial],-1);WaitForSingleObject(chopstick[(m_serial+1)%5],-1); ReleaseSemaphore(People,1,NULL);ReleaseMutex(h_mutex);执行吃饭动作ReleaseSemaphore(chopstick[m_serial],1,NULL);ReleaseSemaphore(chopstick[(m_serial+1)%5],1,NULL);程序源码:#include <windows.h>#include<stdio.h>#define MAX_BUFFER_NUM 4 //最多允许同时去拿筷子的人数#define MAX_THREAD_NUM 5 //创建的进程总数HANDLE h_Thread[MAX_THREAD_NUM]; //存储线程句柄的数组ThreadInfo Thread_Info[MAX_THREAD_NUM]; //线程信息数组struct ThreadInfo{int serial;double delay;};HANDLE chopstick [5]; //创建信号量数组HANDLE People;HANDLE h_mutex;DWORD n_Thread=5; //实际线程数目DWORD n_Buffer_or_Critical=1;void eat(void*p);int main(void){DWORD wait_for_all;for (int k=0;k<5;k++){Thread_Info[k].serial=k;Thread_Info[k].delay=2;}for(int jj=0;jj<(int)n_Thread;jj++) //回显获得的线程信息,便于确认正确性{int Temp_serial=Thread_Info[jj].serial;double Temp_delay=Thread_Info[jj].delay;printf(" \n thread%2d %f",Temp_serial,Temp_delay);}printf("\n\n");for (int i=0;i<5;i++){ chopstick[i]=CreateSemaphore(NULL,n_Buffer_or_Critical,n_Buff er_or_Critical,"chopstick"+i);}People=CreateSemaphore(NULL,MAX_BUFFER_NUM,MAX_BUFFER _NUM,"People");h_mutex=CreateMutex(NULL,FALSE, "mutex_for_update");for (int j=0;j<(int)n_Thread;j++){h_Thread[j]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(eat),& (Thread_Info[j]),0,NULL);}//主程序等待各个线程的动作结束wait_for_all=WaitForMultipleObjects(n_Thread,h_Thread,TRUE,-1);return 0;}void eat(void*p){DWORD //局部变量声明wait_for_semaphore1,wait_for_semaphore2,wait_for_People,wait_for_mutex, m_delay;int m_serial;//获得本线程信息m_serial=((ThreadInfo*)(p))->serial;WaitForSingleObject(h_mutex,-1);WaitForSingleObject(People,-1);printf("哲学家%2d 开始准备拿筷子.\n",m_serial);wait_for_semaphore1=WaitForSingleObject(chopstick[m_serial],-1);wait_for_semaphore2=WaitForSingleObject(chopstick[(m_serial+1)%5],-1);ReleaseSemaphore(People,1,NULL);ReleaseMutex(h_mutex);Sleep(1000);printf("哲学家%2d 开始进餐.\n",m_serial);Sleep(1000);printf( "哲学家%2d 结束进餐.\n",m_serial);ReleaseSemaphore(chopstick[m_serial],1,NULL);ReleaseSemaphore(chopstick[(m_serial+1)%5],1,NULL);}。