实验二 进程(线程)的同步与互斥
- 格式:doc
- 大小:212.00 KB
- 文档页数:8
实验、进程的同步与互斥——⽣产者消费者1. 1. 实验⽬的两个或两个以上的进程,不能同时进⼊关于同⼀组共享变量的临界区域,否则可能发⽣与时间有关的错误,这种现象被称作进程互斥。
对CPU的速度和数⽬不做出任何假设的前提下,并发进程互斥访问临界资源,是⼀个较好的解决⽅案。
另外,还需要解决异步环境下的进程同步问题。
所谓异步环境是指:相互合作的⼀组并发进程,其中每⼀个进程都以各⾃独⽴的、不可预知的速度向前推进;但它们⼜需要密切合作,以实现⼀个共同的任务,即彼此“知道”相互的存在和作⽤。
实验⽬的:分析进程争⽤资源的现象,学习解决进程同步与互斥的⽅法。
本实验属于设计型实验,实验者可根据⾃⾝情况选⽤合适的开发环境和程序架构。
1. 2. 实验原理信号量的PV操作与处理相关,P表⽰通过的意思,V表⽰释放的意思。
1962年,狄克斯特拉离开数学中⼼进⼊位于荷兰南部的艾恩德霍芬技术⼤学(Eindhoven Technical University)任数学教授。
在这⾥,他参加了X8计算机的开发,设计与实现了具有多道程序运⾏能⼒的操作系统——THE Multiprogramming System。
THE是艾恩德霍芬技术⼤学的荷兰⽂Tchnische Hoogeschool Eindhov –en的词头缩写。
狄克斯特拉在THE这个系统中所提出的⼀系统⽅法和技术奠定了计算机现代操作系统的基础,尤其是关于多层体系结构,顺序进程之间的同步和互斥机制这样⼀些重要的思想和概念都是狄克斯特拉在THE中⾸先提出并为以后的操作系统如UNIX等所采⽤的。
为了在单处理机的情况下确定进程(process)能否占有处理机,狄克斯特拉将每个进程分为“就绪”(ready)、“运⾏”(running)和“阻塞”(blocking)三个⼯作状态。
由于在任⼀时刻最多只有⼀个进程可以使⽤处理机,正占⽤着处理机的进程称为“运⾏”进程。
当某进程已具备了使⽤处理机的条件,⽽当前⼜没有处理机供其使⽤,则使该进程处于“就绪”状态。
进程的同步与互斥实验报告1.实验目的进程(线程)的同步与互斥是操作系统中非常重要的概念,本实验旨在通过实际操作,加深对这些概念的理解和掌握。
通过编写多个进程(线程),并在其间进行同步与互斥操作,验证同步与互斥的实际效果。
2.实验环境本实验在Linux系统下进行,使用C/C++语言编程。
3.实验内容3.1同步在实验中,我们编写了两个进程A和B,这两个进程需要按照特定的顺序执行。
为了实现同步,我们使用信号量机制来确保进程A和B按照正确的顺序执行。
3.2互斥在实验中,我们编写了多个进程C和D,这些进程需要同时对一个共享资源进行访问。
为了实现互斥,我们使用互斥锁机制来确保同一时刻只有一个进程访问共享资源。
4.实验过程4.1同步实验编写进程A和进程B的代码,使用信号量机制实现同步。
进程A先运行,然后通过信号量唤醒进程B,进程B再开始执行。
通过观察进程的运行顺序,验证同步机制是否起作用。
4.2互斥实验编写进程C和进程D的代码,使用互斥锁机制实现互斥。
进程C和进程D同时对一个共享资源进行访问,通过互斥锁来确保同一时刻只有一个进程访问共享资源。
观察进程的输出结果,验证互斥机制是否起作用。
5.实验结果5.1同步实验结果进程A开始执行进程A执行完毕进程B开始执行进程B执行完毕5.2互斥实验结果进程C开始执行进程C访问共享资源进程C执行完毕进程D开始执行进程D访问共享资源进程D执行完毕6.实验分析通过上述结果可以看出,同步实验中进程A和进程B按照正确的顺序执行,证明了同步机制的有效性。
互斥实验中进程C和进程D能够正确地交替访问共享资源,证明了互斥机制的有效性。
7.实验总结通过本次实验,我深刻理解了进程(线程)的同步与互斥,并通过实际操作加深了对这些概念的理解。
同步和互斥是操作系统中非常重要的概念,对于应对资源竞争和提高程序性能具有重要意义。
在实际开发中,我们应该合理使用同步和互斥机制,以确保程序的正确性和并发执行的效率。
线程的互斥实验报告总结
本次实验是关于线程互斥的,旨在通过使用互斥锁和信号量等机制,让学生能够更好地理解并掌握线程的互斥操作。
在本次实验中,我们首先学习了互斥锁的概念和使用方法。
互斥
锁是一种最常用的线程同步机制,用来保证多个线程之间的互斥操作。
通过使用互斥锁,我们可以避免两个或多个线程同时访问共享资源而
导致数据异常的问题。
实验中,我们对比了有互斥锁与没有互斥锁对
共享变量的访问结果,明显地看到了在没有互斥锁的情况下,数据会
发生异常。
除了互斥锁,我们还学习了信号量的概念和使用方法。
信号量是
一种用于控制访问共享资源的标志,在多线程程序中广泛应用。
使用
信号量可以保证多个线程间共享资源的安全性,并可以避免资源竞争
和死锁的发生。
在实验中,我们还利用信号量实现了线程的同步和互
斥操作。
通过本次实验,我深感互斥锁和信号量在多线程程序中的重要性。
在多线程编程中,不仅要考虑到线程之间的并发问题,也需要关注到
线程之间的同步和互斥操作。
只有将线程同步和互斥机制运用到多线
程编程中,才能真正保证多线程程序的安全性和正确性。
综上所述,本次实验对于我来说是非常有意义的。
通过学习互斥
锁和信号量等线程同步机制,我对于多线程编程的思想和技术又有了
更深刻的理解和认识。
我相信,在今后的学习和工作中,所学到的知识一定会给我带来更多的帮助和启示。
进程之间同步和互斥的区别和联系
进程之间同步和互斥是操作系统中常见的概念,它们之间有一定的区别和联系。
同步是指多个进程之间的协调,以便它们能够有序地执行。
同步的目的是保证数据的一致性,避免出现数据竞争的情况。
同步可通过共享变量、信号量等方式实现,实现同步的方法包括互斥、条件变量等。
互斥是一种同步机制,用于保护共享资源,防止多个进程同时访问同一资源。
互斥的实现通常是通过临界区实现的,即对于一段代码,只允许一个进程访问,其他进程需要等待。
互斥能够避免多个进程同时写入共享资源,保证了数据的正确性。
同步和互斥的联系在于它们都是为了保证多个进程之间的协调
和数据的正确性。
同步和互斥都是通过对共享资源进行限制来实现的,区别在于同步是为了保证进程的顺序执行,而互斥是为了保证共享资源的安全性。
总的来说,同步和互斥都是操作系统中非常重要的概念,它们的合理运用可以提高操作系统的性能和稳定性。
- 1 -。
详解进程同步与互斥机制⽬录⼀、什么是进程同步⼆、什么是进程互斥三、常见的进程同步与互斥机制⼀、什么是进程同步在多道批处理系统中,多个进程是可以并发执⾏的,但由于系统的资源有限,进程的执⾏不是⼀贯到底的,⽽是⾛⾛停停,以不可预知的速度向前推进,这就是进程的异步性。
那么,进程的异步性会带来什么问题呢?举个例⼦,如果有 A、B 两个进程分别负责读和写数据的操作,这两个线程是相互合作、相互依赖的。
那么写数据应该发⽣在读数据之前。
⽽实际上,由于异步性的存在,可能会发⽣先读后写的情况,⽽此时由于缓冲区还没有被写⼊数据,读进程 A 没有数据可读,因此读进程 A 被阻塞。
进程同步(synchronization)就是⽤来解决这个问题的。
从上⾯的例⼦我们能看出,⼀个进程的执⾏可能影响到另⼀个进程的执⾏,所谓进程同步就是指协调这些完成某个共同任务的并发线程,在某些位置上指定线程的先后执⾏次序、传递信号或消息。
再举个⽣活中的进程同步的例⼦,你想要喝热⽔,于是你打了⼀壶⽔开始烧,在这壶⽔烧开之前,你只能⼀直等着,⽔烧开之后⽔壶⾃然会发⽣响声提醒你来喝⽔,于是你就可以喝⽔了。
就是说⽔烧开这个事情必须发⽣在你喝⽔之前。
注意不要把进程同步和进程调度搞混了:进程调度是为了最⼤程度的利⽤ CPU 资源,选⽤合适的算法调度就绪队列中的进程。
进程同步是为了协调⼀些进程以完成某个任务,⽐如读和写,你肯定先写后读,不能先读后写吧,这就是进程同步做的事情了,指定这些进程的先后执⾏次序使得某个任务能够顺利完成。
⼆、什么是进程互斥同样的,也是因为进程的并发性,并发执⾏的线程不可避免地需要共享⼀些系统资源,⽐如内存、打印机、摄像头等。
举个例⼦:我们去学校打印店打印论⽂,你按下了 WPS 的 “打印” 选项,于是打印机开始⼯作。
你的论⽂打印到⼀半时,另⼀位同学按下了 Word 的 “打印” 按钮,开始打印他⾃⼰的论⽂。
想象⼀下如果两个进程可以随意的、并发的共享打印机资源,会发⽣什么情况?显然,两个进程并发运⾏,导致打印机设备交替的收到 WPS 和 Word 两个进程发来的打印请求,结果两篇论⽂的内容混杂在⼀起了。
线程同步和互斥概念在多线程编程中,线程同步和互斥是非常重要的概念。
线程同步指的是多个线程在执行过程中的协调和合作,以达到共同的目标。
而线程互斥则是指多个线程在访问共享资源时的互相排斥,以保证数据的一致性和正确性。
一、线程同步线程同步是指多个线程之间的协调和合作,以达到共同的目标。
在多线程编程中,线程同步可以通过各种机制来实现,例如锁、信号量、事件等。
1. 锁机制锁机制是最常见的线程同步机制之一。
锁机制可以保证在同一时间只有一个线程可以访问共享资源,其他线程需要等待锁的释放才能访问。
常见的锁有互斥锁、读写锁等。
例如,在一个多线程环境下,多个线程需要访问同一个全局变量,为了保证数据的一致性和正确性,可以使用互斥锁来实现线程同步。
2. 信号量机制信号量机制是另一种常见的线程同步机制。
信号量可以用来控制并发线程的数量,以达到线程同步的目的。
常见的信号量有二元信号量和计数信号量。
例如,在一个多线程环境下,多个线程需要访问同一个共享资源,为了保证数据的一致性和正确性,可以使用计数信号量来控制并发线程的数量。
3. 事件机制事件机制是一种高级的线程同步机制,可以用来实现线程之间的通信和协调。
事件机制通常包括事件对象、事件等待和事件通知等。
例如,在一个多线程环境下,多个线程需要协调完成一项任务,可以使用事件机制来实现线程同步。
二、线程互斥线程互斥是指多个线程在访问共享资源时的互相排斥,以保证数据的一致性和正确性。
在多线程编程中,线程互斥可以通过各种机制来实现,例如锁、信号量、事件等。
1. 锁机制锁机制可以用来实现线程互斥。
在同一时间只有一个线程可以获得锁,其他线程需要等待锁的释放才能访问共享资源。
例如,在一个多线程环境下,多个线程需要访问同一个全局变量,为了保证数据的一致性和正确性,可以使用互斥锁来实现线程互斥。
2. 信号量机制信号量机制也可以用来实现线程互斥。
通过设置信号量的初始值为1,可以保证只有一个线程可以访问共享资源。
操作系统实验进程同步与互斥操作系统实验进程同步与互斥实验目的1.掌握进程同步和互斥原理,理解生产者-消费者模型;2.学习Windows2000/xp中的多线程并发执行机制;3.学习使用Windows SDK解决读者-写者问题。
试验内容1依据生产者-消费者模型,在Windows 2000/xp环境下创建一个控制台进程,在该进程中创建n个线程模拟生产者和消费者,实现进程(线程)的同步与互斥,分析、熟悉生产者消费者问题仿真的原理和实现技术。
(见附件2)试验内容2参考实验内容1和附件2伪码,编程解决读者-写者问题的程序。
(具体要求和读写者问题原始伪码内容见附件1)相关知识Windows 2000/XP的线程控制CreateThread完成线程创建,在调用进程的地址空间上创建一个线程,以执行指定的函数;它的返回值为所创建线程的句柄。
ExitThread用于结束当前线程。
SuspendThread可挂起指定的线程。
ResumeThread可激活指定线程,它的对应操作是递减指定线程的挂起计数,当挂起计数减为0时,线程恢复执行。
Windows 2000/XP的进程互斥和同步在Windows 2000/XP中提供了临界区、互斥对象、信号量对象同步对象和相应的系统调用,用于进程和线程同步。
临界区对象(Critical Section)只能用于在同一进程内使用的临界区,同一进程内各线程对它的访问是互斥进行的。
相关API包括:InitializeCriticalSection对临界区对象进行初始化;EnterCriticalSection等待占用临界区的使用权,得到使用权时返回;TryEnterCriticalSection非等待方式申请临界区的使用权;申请失败时,返回0;LeaveCriticalSection释放临界区的使用权;DeleteCriticalSection释放与临界区对象相关的所有系统资源。
互斥对象(Mutex)互斥对象相当于互斥信号量,在一个时刻只能被一个线程使用。
线程同步和互斥的区别
1. 互斥是指某⼀资源同时只允许⼀个访问者对其进⾏访问,具有唯⼀性和排它性。
但互斥⽆法限制访问者对资源的访问顺序,即访问是
⽆序的。
2. 同步是指在互斥的基础上(⼤多数情况),通过其它机制实现访问者对资源的有序访问。
3. 同步其实已经实现了互斥,所以同步是⼀种更为复杂的互斥。
4. 互斥是⼀种特殊的同步。
所谓互斥,就是不同线程通过竞争进⼊临界区(共享的数据和硬件资源),为了防⽌访问冲突,在有限的时间内只允许其中之⼀独占性的使⽤共享资源。
如不允许同时写
同步关系则是多个线程彼此合作,通过⼀定的逻辑关系来共同完成⼀个任务。
⼀般来说,同步关系中往往包含互斥,同时对临界区的资源会按照某种逻辑顺序进⾏访问。
如先⽣产后使⽤
总的来说,两者的区别就是:
互斥是通过竞争对资源的独占使⽤,彼此之间不需要知道对⽅的存在,执⾏顺序是⼀个乱序。
同步是协调多个相互关联线程合作完成任务,彼此之间知道对⽅存在,执⾏顺序往往是有序的。
lock与unlock⽅法,替换synchronized,这就是互斥锁的体现。
消费者⽣产者模式就是同步锁的体现。
进程同步与互斥总结
进程同步和互斥是操作系统中非常重要的概念,它们都是为了保证多个进程能够在正确的时间顺序和正确的方式下运行。
进程同步是指多个进程之间协调执行的过程,而互斥是指多个进程之间竞争有限资源的过程。
以下是关于进程同步与互斥的一些总结:
1. 进程同步方式:
- 信号量:通过对共享资源的访问进行限制,实现多个进程之间的同步。
- 互斥锁:通过对共享资源的访问进行互斥,实现多个进程之间的同步。
- 条件变量:通过对进程状态的检查,实现多个进程之间的同步。
2. 进程互斥方式:
- 临界区:多个进程同时访问共享资源时,只允许一个进程访问。
- 互斥量:多个进程同时访问共享资源时,通过加锁和解锁来实现互斥。
- 读写锁:多个进程同时访问共享资源时,允许多个进程同时读取,但只允许一个进程写入。
3. 进程同步与互斥的优缺点:
- 信号量:优点是可以同时处理多个进程,缺点是容易出现死锁。
- 互斥锁:优点是简单易用,缺点是只能处理两个进程之间的同步。
- 条件变量:优点是可以检查进程状态,缺点是只能处理两个进
程之间的同步。
- 临界区:优点是简单易用,缺点是只能处理两个进程之间的同步。
- 互斥量:优点是可以同时处理多个进程,缺点是容易出现死锁。
- 读写锁:优点是可以允许多个进程同时读取,缺点是会出现写入延迟的问题。
综上所述,进程同步与互斥是操作系统中非常重要的概念,需要根据具体的场景选择适合的同步方式或互斥方式来保证多个进程之
间的协调执行和有限资源的竞争。
同步与互斥实现方法一、同步与互斥的概念同步是指多个线程或进程之间按照一定的顺序执行,以达到其中一种约定或要求。
在同步的过程中,程序等待其他线程或进程完成一些操作后再继续执行。
互斥是指多个线程或进程之间访问共享资源时,要互相排斥,避免冲突和竞争。
互斥的目的是保证多个线程或进程对共享资源的操作是互斥的,即同一时刻只有一个线程或进程可以访问共享资源。
二、实现同步的方法1. 互斥锁(Mutex)互斥锁是一种最常用的同步机制,通过对一些代码块或函数的访问加上互斥锁的操作,可以保证只有一个线程能够执行该代码块或函数。
当一些线程获得互斥锁时,其他线程在获得该锁之前会被阻塞。
2. 信号量(Semaphore)信号量是一种更为复杂的同步机制,用于实现一些资源的访问控制。
一个信号量有一个整型值和两个原子操作:P和V。
P操作(也称为wait或down)会使信号量的值减1,如果值小于0,当前线程或进程就会被阻塞。
V操作(也称为signal或up)会使信号量的值加1,如果值小于等于0,就会唤醒等待的线程或进程。
信号量可以用于解决生产者-消费者问题、读者-写者问题等并发编程中的资源竞争问题。
3. 条件变量(Condition Variable)条件变量是一种同步机制,用于在多个线程或进程之间同步共享资源的状态。
条件变量对应一个条件,并提供了等待和通知的机制。
等待操作可以使一个线程或进程等待一些条件成立,直到其他线程或进程通知条件变量,使得等待的线程或进程被唤醒。
通知操作可以使等待中的线程或进程被唤醒,继续执行。
条件变量常和互斥锁一起使用,互斥锁用于保护共享资源,条件变量用于同步共享资源的状态。
三、实现互斥的方法1. Peterson算法Peterson算法是一种经典的软件方法,用于解决两个进程之间的互斥访问问题。
该算法使用了两个布尔型变量flag和turn,通过交替使用这两个变量,实现了两个进程之间的互斥。
2. 印章(Semaphores)信号量也可以用于实现互斥操作。
线程互斥的实验报告线程互斥是操作系统中重要的概念之一。
在线程并发执行的情况下,多个线程可能会同时访问共享资源,如果没有互斥机制进行控制,就会出现数据竞争和不确定性的情况。
为了避免这种情况的发生,需要通过互斥机制对多个线程的并发访问进行合理控制。
二、实验目的本实验旨在通过编写程序,实现线程互斥的功能,进一步理解和掌握线程互斥的概念和原理,并验证互斥机制的有效性。
三、实验过程1. 创建共享资源:首先,我们创建一个共享资源,例如全局变量x。
2. 创建多个线程并发执行:通过创建多个线程来模拟多个并发执行的场景,每个线程都有访问共享资源的需求。
3. 创建互斥锁:使用操作系统提供的互斥锁实现机制来实现线程互斥,确保同时只有一个线程可以访问共享资源。
4. 设置互斥锁的加锁和解锁:在线程访问共享资源之前使用互斥锁进行加锁,在访问完共享资源之后进行解锁,以确保资源的正确性和完整性。
5. 运行程序并观察结果:运行多个线程并发执行的程序,通过打印输出等方式观察线程的执行情况,确保互斥机制的有效性。
四、实验结果与分析在实验过程中,我们创建了一个全局变量x作为共享资源,并创建了两个线程t1和t2来同时访问该变量。
通过使用互斥锁的机制,我们保证了同时只有一个线程可以访问变量x。
在线程t1对变量x进行操作之前,需要先获得互斥锁的加锁,操作完成后再进行解锁。
同样地,线程t2在操作变量x之前也需要获得互斥锁的加锁,操作完成后再进行解锁。
经过多次运行实验,观察到线程t1和t2的执行顺序是随机的,有时t1先执行,有时t2先执行。
这是因为线程的调度和执行是由操作系统决定的,而与我们代码编写的顺序无关。
但无论线程t1和t2的执行顺序如何,由于我们使用了互斥锁的机制,保证了对变量x的访问是互斥的,即同时只能有一个线程在操作变量x。
这也是我们对互斥机制的期望结果。
五、实验总结通过本实验,我们深入理解了线程互斥的概念和原理,并成功实现了线程互斥的功能。
操作系统实验报告——进程同步与互斥一、实验内容本实验主要内容是通过编写程序来实现进程的同步与互斥。
具体来说,是通过使用信号量来实现不同进程之间的同步和互斥。
我们将编写两个进程,一个进程负责打印奇数,另一个进程负责打印偶数,两个进程交替打印,要求打印的数字从1开始,直到100结束。
二、实验原理进程的同步是指多个进程之间按照一定的顺序执行,进程之间互相等待的关系。
而进程的互斥是指多个进程竞争同一个资源,需要通过其中一种方式来避免同时访问共享资源,以免造成数据错乱。
在本实验中,我们使用信号量来实现进程的同步与互斥。
信号量是一个计数器,用于表示一些共享资源的可用数量。
进程在访问共享资源时,需要先对信号量进行操作,当信号量大于0时,表示资源可用,进程可以访问;当信号量等于0时,表示资源不可用,进程需要等待。
进程同步的实现可以通过信号量的P操作与V操作来完成。
P操作用于申请资源,当资源可用时,将计数器减一,并进入临界区;V操作用于释放资源,当资源使用完毕时,将计数器加一,使等待资源的进程能够申请。
进程互斥的实现可以通过信号量的P操作与V操作结合临界区来完成。
当多个进程需要访问共享资源时,需要先进行P操作,进入临界区,访问完毕后进行V操作,离开临界区。
三、实验步骤1.首先,我们需要创建两个进程,一个进程负责打印奇数,另一个进程负责打印偶数。
2. 然后,我们创建一个共享变量count,用来记录打印的数字。
3. 接着,我们创建两个信号量odd和even,用来控制进程的同步与互斥。
odd信号量初始值为1,表示打印奇数的进程可以访问;even信号量初始值为0,表示打印偶数的进程需要等待。
4.编写奇数打印进程的代码,首先进行P操作,判断奇数信号量是否大于0,如果大于0,表示可以打印奇数。
5. 如果可以打印奇数,将count加一,并输出当前的奇数,然后进行V操作,释放偶数打印进程的等待。
6.同样的,编写偶数打印进程的代码,首先进行P操作,判断偶数信号量是否大于0,如果大于0,表示可以打印偶数。
南昌大学实验报告---(2)编程模拟进程间的同步和互斥学生姓名:张皓然学号: 5501215001 专业班级:本硕151 实验类型:□验证□综合■设计□创新实验日期: 2017.5.5 实验成绩:一、实验目的通过实验加强对进程同步和互斥的理解,并掌握进程(线程)的创建和调用方法。
学会使用信号量解决资源共享问题。
学生可以自己选择在Windows或Linux系统下编写。
二、实验内容(一)以下为Linux系统下参考程序,请编译、运行并观察程序的输出,并分析实验结果,写出实验报告。
#include<stdio.h>//标准输入输出头文件#include<stdlib.h>//standard library标准库头文件#include<unistd.h>//POSIX标准定义的unix类系统定义符号常量的头文件,包含了许多UNIX系统服务的函数原型,例如read函数、write函数和getpid函数。
#include<time.h>//time.h是C标准库头文件,主要是一些和时间相关的函数#include<sys/types.h>//基本系统数据类型#include<sys/wait.h>//declarations for waiting#include<linux/sem.h>//Semaphore operation flags#define NUM_PROCS 5//5个子进程#define SEM_ID 250//信号量#define FILE_NAME "/tmp/sem_aaa"#define DELAY 4000000void update_file(int sem_set_id, char *file_path, int number){struct sembuf sem_op;FILE *file;//建立一个文件指针//等待信号量的数值变为非负数,此处设为负值,相当于对信号量进行P操作sem_op.sem_num=0;sem_op.sem_op=-1;sem_op.sem_flg=0;semop(sem_set_id,&sem_op,1);/*操作一组信号,进程的标识符号为sem_set_id,sem_op是结构指针。
实验二:编程实现经典互斥和同步问题1.实验目的:加深对信号量、PV操作、进程同步和互斥等概念的理解,掌握PV操作的具体实现方法,熟练掌握进程同步和互斥的实现办法,能利用信号量机制解决实际生活中的同步和互斥问题。
2.实验内容(1)、编程实现P操作原语、V操作原语,(2)、用所定义的PV操作解决下面的问题:设学院某教室共有座位30个,任何时刻最多可容纳30名同学进入自习,当教室内人数少于30名时,则教室外等待的同学可立即进入,否则需在外面等待。
把一个欲进入教室自习的同学看作一个进程。
3、实验具体内容和步骤的说明(1)用户进程的定义(2)信号量的定义及初始化(3)PV操作的定义P操作顺序执行下述两个动作:①信号量的值减1,即S=S-1;②如果S≥0,则该进程继续执行(挂入就绪队列);如果S<0,则把该进程的状态置为阻塞态,把相应的PCB连入该信号量队列的末尾,并放弃处理机,进行等待(直至其它进程在S上执行V操作,把它释放出来为止)。
(挂入阻塞队列)V操作顺序执行下述两个动作:①S值加1,即S=S+1;②如果S>0,则该进程继续运行;(直接挂入就绪队列)如果S≤0,则释放信号量队列上的第一个PCB(即信号量指针项所指向的PCB)所对应的进程(把阻塞态改为就绪态),执行V操作的进程继续运行。
从阻塞队列唤醒一个进程,即从阻塞队列删除,挂入就绪队列(4)写出对应的主函数,解决多名同学之间的同步问题提示:设置2个进程队列,一是已经进入教室的,即就绪队列二是等待进入教室的,即阻塞队列程序:#include <stdio.h>#include <stdlib.h>typedef struct node{int name; //进程IDchar state;//进程状态struct node *next;}PCB;int s=3;//资源数PCB *stophead=NULL,*stoptail=NULL,*readyhead=NULL,*readytail=NULL;//阻塞就绪队列头尾指针void block(PCB *q)//无资源尾插入阻塞队列{q->state='B';if(stophead==NULL){stophead=q;stoptail=q;}else{stoptail->next=q;stoptail=q;}}void wakeup()//唤醒阻塞队列头节点尾插入就绪队列{stophead->state='R';if(readyhead==NULL){readyhead=stophead;readytail=stophead;stophead=stophead->next;readytail->next=NULL;}else{readytail->next=stophead;readytail=stophead;stophead=stophead->next;readytail->next=NULL;}}void p(PCB *q)//p操作{s=s-1;if(s<0)//无资源则插入阻塞队列block(q);else//尾插入就绪队列{q->state='R';if(readyhead==NULL){readyhead=q;readytail=q;}else{readytail->next=q;readytail=q;}}}int v(int b)//v操作{PCB *q,*pre;if(readyhead==NULL)//无就绪进程返回{printf(" 无就绪进程!\n\n");return 0;}pre=readyhead;q=readyhead;while(q->name!=b)//寻找就绪队列中v操作节点{if(q->next==NULL)//无当前查找节点{printf(" 查无此就绪进程!\n\n");return 1;}pre=q;q=q->next;//查找成功if(readyhead==readytail)//就绪队列仅有一个节点{readyhead=readytail=NULL;free(q);s=s+1;return 0;}else//就绪队列有多个节点{if(q==readyhead){readyhead=readyhead->next;free(q);//释放节点}else if(q==readytail){readytail=pre;pre->next=NULL;free(q);}else{pre->next=q->next;free(q);}s=s+1;if(s<=0)//如有阻塞进程则唤醒加入就绪队列wakeup();return 1;}}void show()//输出当前所有进程状态{PCB *q;q=readyhead;printf("\n");printf(" ID STATE\n");while(q!=NULL)printf("%5d%5c\n",q->name,q->state);q=q->next;}q=stophead;while(q!=NULL){printf("%5d%5c\n",q->name,q->state);q=q->next;}}void main(void){PCB *q;char a;int b;printf("\n剩余资源数%d ",s);printf("PLEASE INPUT:");scanf("%c %d",&a,&b);getchar();//输入当前操作类型进程ID (如p 1)while(a!='0')// (0 0)退出{if(a=='p')//执行p操作{q=(PCB *)malloc(sizeof(PCB));//进程初始化q->name=b;q->next=NULL;p(q);}else if(a=='v')//执行v操作b=v(b);if(b!=0)show();//显示当前进程状态printf("\n剩余资源数%d ",s);printf("PLEASE INPUT:");scanf("%c %d",&a,&b);getchar();}}。
实验二线程的同步和互斥问题一.实验内容:编写程序实现并发线程之间的同步和互斥问题。
线程间的互斥:并发执行的线程共享某些类临界资源,对临界资源的访问应当采取互斥的机制。
线程间的同步:并发执行的线程间通常存在相互制约的关系,线程必须遵循一定的规则来执行,同步机制可以协调相互制约的关系。
二.实验目的和要求1)了解进程同步与互斥的概念,掌握编写进程同步、互斥的实例。
2)解决一类典型的进程间同步问题,如生产者-消费者问题,读者-写者问题等。
三.实验方法和步骤1.实验方法掌握同步与互斥的机制,选取合适的问题,给出演示程序的设计思想,包括流程图的形式;选取C、C++、VC、JA V A等计算机语言,编程调试,最终给出运行正确的程序。
2.程序设计(1)线程间互斥:分析问题,创建多个线程,找出临界资源,划出正确的临界区,根据互斥机制的操作模式,编写程序。
互斥机制的操作模式:p(mutex);/*关锁*/临界区的操作;v(mutex);/*开锁*/(2)线程间同步——读者-写者问题示例:在Windows 2000 环境下,创建一个包含n 个线程的控制台进程。
用这n 个线程来表示n个读者或写者。
每个线程按相应测试数据文件的要求,进行读写操作。
请用信号量机制分别实现读者优先和写者优先的读者-写者问题。
读者-写者问题的读写操作限制:1)写-写互斥;2)读-写互斥;3)读-读允许;运行结果显示要求:要求在每个线程创建、发出读写操作申请、开始读写操作和结束读写操作时分别显示一行提示信息,以确信所有处理都遵守相应的读写操作限制。
测试数据文件格式测试数据文件包括n 行测试数据,分别描述创建的n 个线程是读者还是写者,以及读写操作的开始时间和持续时间。
每行测试数据包括四个字段,各字段间用空格分隔。
第一字段为一个正整数,表示线程序号。
第二字段表示相应线程角色,R 表示读者是,W 表示写者。
第三字段为一个正数,表示读写操作的开始时间。
操作系统实验报告-进程同步与互斥(总12页)--本页仅作为文档封面,使用时请直接删除即可----内页可以根据需求调整合适字体及大小--《进程同步与互斥》实验报告学号姓名专业、班实验地点指导教师时间一、实验目的1、掌握基本的进程同步与互斥算法,理解生产者-消费者问题。
2、学习使用Windows 2000/XP中基本的同步对象,掌握相关API的使用方法。
3、了解Windows 2000/XP中多线程的并发执行机制,实现进程的同步与互斥。
4、设计程序,实现生产者-消费者进程(线程)的同步与互斥;二、实验环境Windows 2000/XP + Visual C++三、实验内容以生产者-消费者模型为依据,在Windows 2000/XP环境下创建一个控制台进程,在该进程中创建n个线程模拟生产者和消费者,实现进程(线程)的同步与互斥。
四、设计思路和流程框图生产者进程的功能:生产东西,供消费者消费;消费者进程的功能:消费生产者生产的东西。
生产者生产产品并存入缓冲区供消费者取走使用,消费者从缓冲器内取出产品去消费。
在生产者和消费者同时工作时,必须禁止生产者将产品放入已装满的缓冲器内,禁止消费者从空缓冲器内取产品。
五、源程序(含注释)清单六、测试结果以及实验总结1、通过实验进一步了解了基本的进程同步与互斥算法,理解生产者-消费者问题2、掌握了相关API的使用方法。
3、了解到进程是一个可以拥有资源的基本单位,是一个可以独立调度和分派的基本单位。
而线程是进程中的一个实体,是被系统独立调度和分配的基本单位,故又称为轻权(轻型)进程(Light Weight Process)。
4、了解到同步对象是指Windows中用于实现同步与互斥的实体,包括信号量(Semaphore)、互斥量(Mutex)、临界区(Critical Section)和事件(Events)等。
本实验中使用到信号量、互斥量和临界区三个同步对象。
成绩备注:实验报告文档的名称:姓名_实验编号(例如:张三_1、张三_2);实验报告发送到。
学生实验报告姓名:年级专业班级学号成绩#define N 1 //N定义为临界资源!printf("请输入三个进程:\n"); //初始状态为:临界资源处于空闲状态!loop:scanf("%d %d %d",&a,&b,&c); //输入的进程名为:a,b,c!进程名输入的先后代表进程的访问顺序!if(a==N) //判断进程a是否占据临界资源!若a==N,表明a访问临界资源!{printf("a=%d\n",a); //a正在访问临界资源!printf("b=0,c=0\n"); //b,c不能进入自己的临界区,需等待a释放临界资源!printf(“临界资源正在被进程a访问,进程b,c必须等待.\n”);}else if(b==N){printf("b=%d\n",b); //b正在访问临界资源!printf("a=0,c=0\n"); //a,c不能进入自己的临界区,需等待b释放临界资源!printf(“临界资源正在被进程b访问,进程a,c必须等待.\n”);}5.编译链接所编写的程序,在编译正确的情况下执行程序.6.记录程序执行的结果(如下图所示).注意:初始状态为:临界资源处于空闲状20 10年12 月16 日【实验结果或总结】(对实验结果进行相应分析,或总结实验的心得体会,并提出实验的改进意见)1.进程a,b,c分别访问临界资源时程序执行的结果如下.(a) (b) (c)2.该程序初始化N为临界资源,根据输入a,b,c,的值是否等于N来判断进程分别是否进入自己的临界区。
当a=N 表明进程a正在访问临界资源。
此时程序执行的输出为:a=1,b=c=0表示进程b,c不能进入自己的临界区。
3.该程序能较好地体现程序并发执行时的一种制约关系-互斥,但不能较好的反映进程的同步关系,所以该算法有待改进,用以同时实现进程的同步和互斥。
实验二 进程(线程)的同步与互斥一、实验目的1. 掌握基本的同步与互斥算法,理解生产者消费者模型。
2. 学习使用Windows 中基本的同步对象,掌握相关API 的使用方法。
3. 了解Windows 中多线程的并发执行机制,实现进程的同步与互斥。
二、实验内容1. 实验内容以生产者/消费者模型为依据,在Windows 环境下创建一个控制台进程,在该进程中创建n 个线程模拟生产者和消费者,实现进程(线程)的同步与互斥。
2. 实验要求● 学习并理解生产者/消费者模型及其同步/互斥规则; ● 学习了解Windows 同步对象及其特性; ● 熟悉实验环境,掌握相关API 的使用方法;● 设计程序,实现生产者/消费者进程(线程)的同步与互斥;三、相关API 的功能及使用我们利用Windows SDK 提供的API 编程实现实验题目要求,而VC 中包含有Windows SDK 的所有工具和定义。
要使用这些API ,需要包含堆这些函数进行说明的SDK 头文件——最常见的是Windows.h(特殊的API 调用还需要包含其他头文件)。
下面给出的是本实验使用到的API 的功能和使用方法简单介绍。
(1) CreateThread● 功能——创建一个在调用进程的地址空间中执行的线程 ● 格式HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes,DWORD dwStackSize,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParamiter,Buffer(共享内存)生产者消费者DWORD dwCreationFlags,Lpdword lpThread );●参数说明lpThreadAttributes——指向一个LPSECURITY_ATTRIBUTES(新线程的安全性描述符)。
dwStackSize——定义原始堆栈大小。
lpStartAddress——指向使用LPTHRAED_START_ROUTINE类型定义的函数。
lpParamiter——定义一个给进程传递参数的指针。
dwCreationFlags——定义控制线程创建的附加标志。
lpThread——保存线程标志符(32位)(2) CreateMutex●功能——创建一个命名或匿名的互斥量对象●格式HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes,BOOL bInitialOwner,LPCTSTR lpName);●参数说明lpMutexAttributes——必须取值NULL。
bInitialOwner——指示当前线程是否马上拥有该互斥量(即马上加锁)。
lpName——互斥量名称。
(3) CreateSemaphore●功能——创建一个命名或匿名的信号量对象●格式HANDLE CreateSemaphore(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,LONG lInitialCount,LONG lMaximumCount,LPCTSTR lpName );●参数说明lpSemaphoreAttributes——必须取值NULL。
lInitialCount——信号量的初始值。
该值大于等于0,但小于等于lMaximumCount指定的最大值。
lMaximumCount——信号量的最大值。
lpName——信号量名称。
(4) WaitForSingleObject●功能——使程序处于等待状态,直到信号量hHandle出现(即其值大于0)或超过规定的等待时间●格式DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);●参数说明hHandle——信号量指针。
dwMilliseconds——等待的最长时间(INFINITE为无限等待)。
(5) ReleaseSemaphore●功能——对指定信号量加上一个指定大小的量。
成功执行则返回非0值●格式BOOL ReleaseSemaphore(HANDLE hSemaphore,LONG lReleaseCount,LPLONG lppreviousCount );●参数说明hSemaphore——信号量指针。
lReleaseCount——信号量的增量。
lppreviousCount——保存信号量当前值。
(6) ReleaseMutex●功能——打开互斥锁,即把互斥量加1。
成功调用则返回0●格式BOOL ReleaseMutex(HANDLE hMutex);●参数说明hMutex——互斥量指针。
四、示例程序//定义一个结构体用于存储线程的信息struct ThreadInfo{int serial; //线程号char entity; //线程类别(生产者或消费者)double delay; //等待时间double persist; //操作时间};//生产者void Producer(void *p){//定义变量用于存储当前线程的信息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,INFINITE);cout<<"生产者线程"<<m_serial<<" 请求独占缓冲区."<<endl;WaitForSingleObject(g_hMutex,INFINITE);Sleep(m_delay); //延迟等待//生产一个产品cout<<"生产者线程"<<m_serial<<" 生产"<<++ProductID <<" 号产品成功." <<endl;cout<<"生产者线程"<<m_serial<<" 请求将产品"<<ProductID<<" 投入缓冲区."<<endl;//把新生产的产品放入缓冲区g_buffer[in] = ProductID;in = (in+1)%SIZE_OF_BUFFER;Sleep(m_persist); //操作等待cout<<"生产者线程"<<m_serial<<" 将产品"<<ProductID<<" 投入缓冲区中成功."<<endl;//输出缓冲区当前的状态cout<<"****************************"<<endl<<"\n当前缓冲区情况如图(■代表已有产品,□代表没有产品): "<<endl;for (int i = 0;i<10;i++){if( g_buffer[i]>0 ) cout<<"■";else cout<<"□";}cout<<"\n\n****************************\n"<<endl;//V操作ReleaseMutex(g_hMutex);ReleaseSemaphore(g_hFullSemaphore,1,NULL);}}//消费者void Consumer(void *p) {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_hFullSemaphore,INFINITE);cout<<"消费者线程"<<m_serial<<" 请求独占缓冲区."<<endl;WaitForSingleObject(g_hMutex,INFINITE);Sleep(m_delay); //延迟等待//从缓冲区中取出一个产品cout<<"消费者线程"<<m_serial<<" 请求取出一个产品."<<endl;ConsumeID = g_buffer[out];g_buffer[out]=0;out = (out+1)%SIZE_OF_BUFFER;cout<<"消费者线程"<<m_serial<<" 取出产品"<<ConsumeID<<" 成功."<<endl;//消耗一个产品cout<<"消费者线程"<<m_serial<<" 开始消费消费产品" <<ConsumeID<<"."<<endl;Sleep(m_persist);cout<<"消费者线程"<<m_serial<<" 消费产品" <<ConsumeID<<" 成功."<<endl;//输出缓冲区当前的状态cout<<"****************************"<<endl<<"\n当前缓冲区情况如图: "<<endl;for ( int i= 0;i<10;i++){if(g_buffer[i]>0 )cout<<"■";else cout<<"□";}cout<<"\n\n****************************\n"<<endl;//V操作ReleaseMutex(g_hMutex);ReleaseSemaphore(g_hEmptySemaphore,1,NULL);}}五、实验结果六、实验结果分析1、记录生产者和消费者的同步执行过程线程号线程类别延迟时间操作时间操作请求缓冲区请求生产(消费)结果1 P 12 请求生产请求独占(在2前)生产成功2 P 2 6 请求生产请求独占未生产3 C45 请求消费无未消费4 C56 请求消费无未消费5 C 3 2 无无未消费2、分析Producer函数和Consumer函数的功能,并画出对应的程序流程图。