多线程编程实验_进程-线程的同步
实验1编程实现进程(线程)同步和互斥

实验1编程实现进程(线程)同步和互斥一、实验目的①通过编写程序实现进程同步和互斥,使学生掌握有关进程(线程)同步与互斥的原理,以及解决进程(线程)同步和互斥的算法,从而进一步巩固进程(线程)同步和互斥②等有关的内容。
③了解Windows2000/XP中多线程的并发执行机制,线程间的同步和互斥。
④学习使用Windows2000/XP中基本的同步对象,掌握相应的⑤API函数。
⑥掌握进程和线程的概念,进程(线程)的控制原语或系统调用的使用。
⑦掌握多道程序设计的基本理论、方法和技术,培养学生多道程序设计的能力。
二、实验内容在Windows XP、Windows 2000等操作系统下,使用的VC、VB、java或C等编程语言,采用进程(线程)同步和互斥的技术编写程序实现生产者消费者问题或哲学家进餐问题或读者-写者问题或自己设计一个简单进程(线程)同步和互斥的实际问题。
三、实验要求①经调试后程序能够正常运行。
②采用多进程或多线程方式运行,体现了进程(线程)同步和互斥的关系。
③程序界面美观。
四、实验步骤、过程让写者与读者、读者与读者之间互斥的访问同一数据集,在无写者进程到来时各读者可同时的访问数据集,在读者和写者同时等待时写者优先唤醒。
设置两个全局变量readcount 和writecount来记录读者与写者的数目,设置了3个信号量。
h_mutex1表示互斥对象对阻塞在read这一个过程实现互斥,h_mutex2实现全局变量readcount操作上的互斥,h_mutex3实现对全局变量writecount的互斥访问。
设置了两个临界区,为了实现写者优先,用了临界区read。
数据结构:(1)用了两个临界区(2)自定义结构ThreadInfo记录一条线程信息,多个线程对应一个ThreadInfo数组。
(3)设置了互斥量h_mutex1,实现了互斥对象对阻塞read这一过程,h_mutex2实现对readcount操作的互斥,h_mutex3实现对writecount的互斥访问。
进程的同步与互斥实验报告

进程的同步与互斥实验报告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.实验总结通过本次实验,我深刻理解了进程(线程)的同步与互斥,并通过实际操作加深了对这些概念的理解。
同步和互斥是操作系统中非常重要的概念,对于应对资源竞争和提高程序性能具有重要意义。
在实际开发中,我们应该合理使用同步和互斥机制,以确保程序的正确性和并发执行的效率。
多线程同步的实现方法

多线程同步的实现方法在多线程编程中,为了保证数据的正确性和程序的稳定性,需要使用同步机制来控制不同线程之间对共享资源的访问。
本文将介绍几种常见的多线程同步实现方法。
一、互斥锁互斥锁是最基本也是最常用的一种同步机制。
它通过对共享资源加锁来防止其他线程同时访问该资源,从而避免数据竞争和冲突问题。
当一个线程获得了该锁后,其他想要访问该资源的线程就必须等待其释放锁才能进行操作。
在C++11标准中提供了std::mutex类作为互斥量,在使用时可以调用lock()函数获取锁并执行相应操作,再调用unlock()函数释放锁。
需要注意的是,在使用时应尽可能缩小临界区范围以提高效率,并确保所有涉及到共享资源修改或读取操作都被包含在临界区内。
二、条件变量条件变量通常与互斥锁结合起来使用,用于协调不同线程之间对某个事件或状态变化进行响应和处理。
当某个条件满足时(如队列非空),唤醒等待该条件变量上阻塞着的一个或多个进入等待状态(wait)的进程,使其重新参与竞争获取所需资源。
C++11标准库中提供了std::condition_variable类作为条件变量,在使用前需要先创建一个std::unique_lock对象并传递给wait()函数以自动解除已有lock对象,并将当前进入等待状态直至被唤醒;notify_one() 和 notify_all() 函数则分别用于唤醒单个或全部处于等待状态下面向此条件变量发出请求者。
三、信号量信号量是一种更复杂但功能更强大的同步机制。
它通过计数器记录可用资源数量,并根据计数器值判断是否允许新建任务运行或者挂起正在运行任务以便其他任务可以获得所需资源。
其中P(Proberen)表示申请/获取信号灯, V(Verhogen)表示释放/归还信号灯.C++11标准库没有直接支持Semaphore,但我们可以利用mutex+condition_variable模拟实现Semaphore. 其核心思想就是:定义两个成员属性count_ 和 mutex_, count_ 表示当前可申请 Semaphore 的数量 , mutex_ 是 std::mutex 类型 , 定义两个成员方法 wait(), signal(). 四、原子操作原子操作指不能被打断、干扰或交错执行影响结果正确性的操作。
多线程程序实验报告(3篇)

第1篇一、实验目的1. 理解多线程的概念和作用。
2. 掌握多线程的创建、同步和通信方法。
3. 熟悉Java中多线程的实现方式。
4. 提高程序设计能力和实际应用能力。
二、实验环境1. 操作系统:Windows 102. 开发工具:IntelliJ IDEA3. 编程语言:Java三、实验内容本次实验主要完成以下任务:1. 创建多线程程序,实现两个线程分别执行不同的任务。
2. 使用同步方法实现线程间的同步。
3. 使用线程通信机制实现线程间的协作。
四、实验步骤1. 创建两个线程类,分别为Thread1和Thread2。
```javapublic class Thread1 extends Thread {@Overridepublic void run() {// 执行Thread1的任务for (int i = 0; i < 10; i++) {System.out.println("Thread1: " + i);}}}public class Thread2 extends Thread {@Overridepublic void run() {// 执行Thread2的任务for (int i = 0; i < 10; i++) {System.out.println("Thread2: " + i);}}}```2. 创建一个主类,在主类中创建两个线程对象,并启动它们。
```javapublic class Main {public static void main(String[] args) {Thread thread1 = new Thread1();Thread thread2 = new Thread2();thread1.start();thread2.start();}```3. 使用同步方法实现线程间的同步。
```javapublic class SynchronizedThread extends Thread {private static int count = 0;@Overridepublic void run() {for (int i = 0; i < 10; i++) {synchronized (SynchronizedThread.class) {count++;System.out.println(Thread.currentThread().getName() + ": " + count);}}}}public class Main {public static void main(String[] args) {Thread thread1 = new SynchronizedThread();Thread thread2 = new SynchronizedThread();thread1.start();thread2.start();}```4. 使用线程通信机制实现线程间的协作。
多线程同步的几种方法

多线程同步的几种方法
多线程同步的几种方法主要包括临界区、互斥量、信号量、事件和读写锁等。
这些方法可以有效地控制多个线程对共享资源的访问,避免出现数据不一致和线程冲突的问题。
1.临界区:通过临界区实现多个线程对某一公共资源或一段代码的串行访问,可以保证某一时刻只有一个线程访问某一资源,速度快,适合控制数据的访问。
2.互斥量:互斥量是最简单的同步机制,即互斥锁。
多个进程(线程)均可以访问到一个互斥量,通过对互斥量加锁,从而来保护一个临界区,防止其它进程(线程)同时进入临界区,保护临界资源互斥访问。
3.信号量:信号量可以控制有限用户对同一资源的的访问而设计。
4.事件:通过通知线程的有一些事件已经发生,从而可以启动后续的任务执行。
5.读写锁:读写锁适合于使用在读操作多、写操作少的情况,比如数据库。
读写锁读锁可以同时加很多,但是写锁是互斥的。
当有进程或者线程要写时,必须等待所有的读进程或者线程都释放自己的读锁方可以写。
数据库很多时候可能只是做一些查询。
以上信息仅供参考,如有需要,建议咨询专业编程技术
人员。
多线程之线程同步的方法(7种)

多线程之线程同步的⽅法(7种)同步的⽅法:⼀、同步⽅法 即有synchronized关键字修饰的⽅法。
由于java的每个对象都有⼀个内置锁,当⽤此关键字修饰⽅法时,内置锁会保护整个⽅法。
在调⽤该⽅法前,需要获得内置锁,否则就处于阻塞状态。
注: synchronized关键字也可以修饰静态⽅法,此时如果调⽤该静态⽅法,将会锁住整个类。
⼆、同步代码块 即有synchronized关键字修饰的语句块。
被该关键字修饰的语句块会⾃动被加上内置锁,从⽽实现同步代码如:synchronized(object){}注:同步是⼀种⾼开销的操作,因此应该尽量减少同步的内容。
通常没有必要同步整个⽅法,使⽤synchronized代码块同步关键代码即可。
package com.xhj.thread;/*** 线程同步的运⽤** @author XIEHEJUN**/public class SynchronizedThread {class Bank {private int account = 100;public int getAccount() {return account;}/*** ⽤同步⽅法实现** @param money*/public synchronized void save(int money) {account += money;}/*** ⽤同步代码块实现** @param money*/public void save1(int money) {synchronized (this) {account += money;}}}class NewThread implements Runnable {private Bank bank;public NewThread(Bank bank) {this.bank = bank;}@Overridepublic void run() {for (int i = 0; i < 10; i++) {// bank.save1(10);bank.save(10);System.out.println(i + "账户余额为:" + bank.getAccount());}}}/*** 建⽴线程,调⽤内部类*/public void useThread() {Bank bank = new Bank();NewThread new_thread = new NewThread(bank);System.out.println("线程1");Thread thread1 = new Thread(new_thread);thread1.start();System.out.println("线程2");Thread thread2 = new Thread(new_thread);thread2.start();}public static void main(String[] args) {SynchronizedThread st = new SynchronizedThread();eThread();}}=====================================⽰例加讲解同步是多线程中的重要概念。
C#实现多线程的同步方法详解

C#实现多线程的同步⽅法详解本⽂主要描述在C#中线程同步的⽅法。
线程的基本概念⽹上资料也很多就不再赘述了。
直接接⼊主题,在多线程开发的应⽤中,线程同步是不可避免的。
在.Net框架中,实现线程同步主要通过以下的⼏种⽅式来实现,在MSDN的线程指南中已经讲了⼏种,本⽂结合作者实际中⽤到的⽅式⼀起说明⼀下。
1. 维护⾃由锁(InterLocked)实现同步2. 监视器(Monitor)和互斥锁(lock)3. 读写锁(ReadWriteLock)4. 系统内核对象1) 互斥(Mutex), 信号量(Semaphore), 事件(AutoResetEvent/ManualResetEvent)2) 线程池除了以上的这些对象之外实现线程同步的还可以使⽤Thread.Join⽅法。
这种⽅法⽐较简单,当你在第⼀个线程运⾏时想等待第⼆个线程执⾏结果,那么你可以让第⼆个线程Join进来就可以了。
⾃由锁(InterLocked)对⼀个32位的整型数进⾏递增和递减操作来实现锁,有⼈会问为什么不⽤++或--来操作。
因为在多线程中对锁进⾏操作必须是原⼦的,⽽++和--不具备这个能⼒。
InterLocked类还提供了两个另外的函数Exchange, CompareExchange⽤于实现交换和⽐较交换。
Exchange操作会将新值设置到变量中并返回变量的原来值: int oVal = InterLocked.Exchange(ref val, 1)。
监视器(Monitor)在MSDN中对Monitor的描述是: Monitor 类通过向单个线程授予对象锁来控制对对象的访问。
Monitor类是⼀个静态类因此你不能通过实例化来得到类的对象。
Monitor 的成员可以查看MSDN,基本上Monitor的效果和lock是⼀样的,通过加锁操作Enter设置临界区,完成操作后使⽤Exit操作来释放对象锁。
不过相对来说Monitor的功能更强,Moniter可以进⾏测试锁的状态,因此你可以控制对临界区的访问选择,等待or离开, ⽽且Monitor还可以在释放锁之前通知指定的对象,更重要的是使⽤Monitor可以跨越⽅法来操作。
进程同步实验报告

一、实验目的1. 理解进程同步的概念和原理;2. 掌握进程同步的基本方法和机制;3. 学会使用信号量实现进程同步;4. 通过实验验证进程同步机制的有效性。
二、实验原理1. 进程同步:在多道程序设计中,进程的执行是并发的,但某些情况下需要保证多个进程按照一定的顺序执行,以避免出现数据不一致、死锁等问题。
进程同步是指通过某种机制,协调多个进程的执行顺序,保证它们能够正确、有效地共享资源。
2. 信号量:信号量是一种特殊的变量,用于实现进程同步。
信号量具有两个原子操作:P操作(wait)和V操作(signal)。
P操作用于申请资源,V操作用于释放资源。
3. 互斥锁:互斥锁是一种常见的进程同步机制,用于保证临界资源的互斥访问。
当一个进程进入临界区时,它会尝试获取互斥锁,如果锁已被其他进程获取,则该进程进入等待状态;当进程退出临界区时,它会释放互斥锁。
三、实验内容1. 实验环境:Linux操作系统,C语言编程环境。
2. 实验工具:gcc编译器、gdb调试器。
3. 实验步骤:(1)创建一个互斥锁,用于保护临界资源。
(2)编写两个进程,分别模拟对临界资源的访问。
(3)在进程访问临界资源前,使用P操作尝试获取互斥锁。
(4)在进程访问临界资源后,使用V操作释放互斥锁。
(5)编译并运行程序,观察进程执行情况。
四、实验结果与分析1. 实验结果:(1)在互斥锁的保护下,两个进程能够按照预期顺序访问临界资源。
(2)当其中一个进程正在访问临界资源时,另一个进程会进入等待状态。
(3)当进程访问临界资源完成后,它会释放互斥锁,允许其他进程访问。
2. 实验分析:(1)互斥锁能够有效地保护临界资源,避免数据不一致问题。
(2)信号量P操作和V操作保证了进程的同步,避免了死锁现象。
(3)通过实验验证了进程同步机制的有效性。
五、实验总结本次实验通过使用信号量和互斥锁,实现了进程同步。
实验结果表明,信号量和互斥锁能够有效地保证进程按照预期顺序执行,避免数据不一致和死锁等问题。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
I 进程/线程的同步1 项目概述2 创建竞态3 临界区问题的解决办法4 实现一般信号量5 有界缓冲区6 具体任务总结7 附加任务的建议1 项目概述在本项目中,我们将使用不同的方法来解决临界区问题和有界缓冲区问题。
第一个任务是建立两个访问同一个共享资源的并发线程。
我们将证明没有同步机制时,线程执行的一些操作可能会丢失。
然后我们实现两种不同的解决方案:(1)利用Pthreads提供的互斥锁(mutex locks);(2)使用一种软件解决方案(Peterson方法),并比较这两种方法的性能。
然后我们会实现两种不同的作用于一般信号量的P操作和V操作;(1)利用Pthreads提供的互斥锁(mutex locks)和环境变量;(2)使用软件解决方法。
再比较两者的性能。
最后,我们利用上面的平台开发的P操作和V操作在两个并发线程之间实现一个有界缓冲区。
2 创建竞态在本项目中,我们采用POSIX的Pthreads,当然也可以使用能够提供一个进程中有多个线程的其它程序包。
POSIX标准没有规定在多个线程之间具体的并发需求。
我们首先假设要实现需要支持RR调度的并发线程。
这就是说,每个线程运行一段时间以后将被自动抢占,另一个线程开始执行。
因此,在一个进程中的所有线程都以不可预知的速度并发运行。
为创建一个竞态,创建两个线程T1和T2。
父线程(主线程)定义了两个全局变量accnt1和accnt2。
每个变量表示一个银行账户,且只有一个值(当前余额),其初值为0。
线程模拟银行事务,即将一定数额的钱从一个账户转移到另一个账户。
这就是说,每个线程都要读取两个账户的数值,产生一个随机数r,把这个数增加到另一个账户上,并从另一个账户上减去该值。
下面的代码框架说明了每个线程的操作:counter=0;do {temp1=accnt1;temp2=accnt2;r=rand();accnt1=temp1+r;accnt2=temp2-r;counter++;}while(accnt1+accnt2==0);print(counter);两个线程执行相同的代码。
中要没有交叉执行,两个余额的和将会是0。
然而,如果线程交叉执行,一个线程可能读取accnt1原来的值和accnt2的新值,或者相反,这就会导致丢失其中一个更新后的值。
如果发现这种情况,线程将停止并打印出发生时的步长(counter)。
也可以利用文件创建一个类似的程序。
主线程创建两个共享文件f1和f2,并利用它们替换共享变量accnt1和accnt2。
每个文件只有一个值——当前账户余额。
线程使用和上面程序相同的方法,利用一个随机数读取和更新余额(注意,在读/写序列中一定不能为了互斥性访问而锁住文件,否则将不能交叉执行)。
为主线程和两个线程代码。
然后测试多长时间会产生一次竞态,从而造成更新值的丢失。
注意:在实现不支持RR调度的线程时,必须通过在线程之间显式地强制实施文境切换来模拟这种行为。
在两个更新语句之间插入一段代码执行如下操作:在指定的范围内(如从0~1)产生一个随机数。
如果该数比某个给定的阈值(如0.1)小,便使用一个yield语句明确地将CPU让给其它线程。
这样平均下来,在10次循环中就会有1次产生文境切换。
3 临界区问题的解决方法在每个线程的代码中都有一个临界区。
解决这个问题有两种可能方法。
如果系统提供了如互斥量的基本同步原语,就可以用它锁住临界区实现互斥访问。
如果系统没有提供任何同步原语,就可以使用软件方法(由Peterson开发的方法,见原理教材的相关章节的介绍)。
下面我们对这两方法进行讨论和比较。
3.1 使用互斥锁的解决方法Pthread库提供了一种二元信号量,被称作互斥量(mutexes)。
互斥量可以被加锁和解锁。
当为一个已被其它线程锁住的互斥量再次上锁时,调用线程将被阻塞直到该互斥量被解锁。
利用这些原语很容易实现临界区。
在进入临界区前,互斥量将被加锁。
我们的实例中,是在第一次读操作之前加锁的。
在离开临界区后,互斥量才被解锁。
实例中是在第二次更新之后解锁的。
由系统事处理正在阻塞(正在等待)和正被解锁的线程。
3.2 软件解决方法现在我们假设系统没有提供互斥量或者其它任何形式的同步原语。
我们只能利用标准编程语言在常规变量上的操作来解决临界区问题。
在原理教材中提到的解决两个进程或线程之间临界区问题的方法使用了3个变量c1、c2和will_wait。
当线程i想进入临界区时,便将变量ci置为1。
为了打破任何可能存在的竞态,也要将will_wait设为j。
以忙等待循不的形式在临界区之前实现阻塞。
当线程离开临界区时,再把变量ci重置为0。
我们的临界区是一段代码,它以第一次读操作开始,以第二次更新操作结束。
我们可以使用软件方法中的代码实施互斥。
为了加快执行速度,忙等待循环应该包含sched_yield语句。
这样阻塞时便会马上释放CPU,而不是在时间片过时前一直在空循环。
现在我们准备比较解决临界区问题的两种方法的效率。
利用两种方法简单地重复相同次数的循环并测量执行时间。
为了消除任何可能的外部干扰,重复试验几次,计算平均时间。
4 实现一般信号量使用更低级的原语,如二元信号量,可以方便地实现一般信号量的P操作和V操作。
换句话说,可以尝试只用常规编程结构的解决方法。
4.1 使用互斥锁和条件变量的解决方法在原理教材中讨论了如何使用二元信号量上的Pb操作和Vb操作来实现一般信号量的P操作和V操作。
这种方法使用了两个二元信号量sb和delay。
它们有着不同的用途。
sb用于互斥。
这种信号量同Pthreads中的互斥锁类似。
这样,我们可以使用Pb(sb)和Vb(sb)分别代替mutex_lock和mutex_unlock。
二元信号量delay用于在P操作中阻塞进程,然后释放进程(使用相应的V操作)。
这种二元信号量可以用条件变量来模拟。
那么,pthread_cond_wait和pthread_cond_signal 将分别对应于Pb(delay)和Vb(delay)。
4.2 软件解决方法在前一节中,我们已经有了解决临界区问题的一种软件方法(就是没有使用任何特殊的同步指令的方法)。
按照如下步骤,我们可以创建用于临界区的P操作和V操作:(1)每个信号量s使用一个整数变量实现。
(2)对共享变量s的访问必须以临界区的方式实现。
(3)当P操作必须阻塞时,线程必须进入一个不停测试s值的while循环(在临界区内),直到s比0大;与此同时它要减少s的值,并继续继续执行。
在等待循环的每次迭代中,线程应该放弃CPU以便提高性能。
(注意:放弃操作不应在临界区内发生。
否则,没有其他进程能够执行V操作,这样系统将会发生死锁。
)(4)V操作会简单地增加s的值(在临界区内)。
现在,我们准备比较两种实现P操作和V操作方法的性能。
开发一些测试用例,它们包括一个或多个执行不同顺序的P操作和V操作的线程。
需要特别指出的是,应当测试一下在P操作中没有线程等待的情况下和在P操作中有一个线程或多个线程等待的情况下P操作和V操作的执行时间。
5 有界缓冲区在原理教材中讨论了在一个生产者线程和一个消费者线程之间实现有界缓冲区的问题。
生产者线程从一个文件f1中反复读取数据(如一个整数),直到到达文件末尾。
它把每个数据存放到利用大小为n的数组所实现的有界缓冲区中,并在两个进程之间共享该数组。
消费者线程不停地从缓冲区中移出数据,并把它们写入到另一个文件f2中。
当两个线程都完成时,文件f2应该是文件f1的完全副本。
记录每次循环中有多少值会在缓冲区里。
如果值大部份时间要么是n要么是0,那么就可以把随机选择睡眠一段时间的sleep语句插入到生产者和消费者线程的循环体中,以模拟消费和生产活动的突发情况。
6 具体任务总结(1)创建两个线程,使它们进入一个竞态。
(2)使用(a)互斥锁;(b)Peterson软件方法来解决竞态问题,并比较两者的性能。
(3)分别使用(a)互斥锁和环境变量;(b)解决临界区问题的软件方法来实现对一般信号量的P操作和V操作的。
并比较两种方法的性能。
(4)在生产者和消费者线程问题之间实现一个有界缓冲。
研究两个线程的并发行为。
(5)将你的试验结果写成报告7 附加任务的建议(1)使用P操作和V操作实现基本的管程功能。
这就需要写一个预编译器。
该预编译器使用原理教材中实现的代码替换所有的c.wait和s.signal操作,并插入互斥代码使其围绕着每一个管程过程。
然后,并发线程可以调用管程过程来协调它们对共享资源的使用。
还有,为了将过程和资源封装在一起建模,可以将管程实现为一个独立的进程。
该进程与其它必须借助于UNIX管道来使用管程的进程进行进行通信。
当一个进程试图调用一个管道过程时,它通过向请求管道写入信息的方式,向管程进程发出请求(包括程序和参数)。
然后从应答管道中读取信息并阻塞自己。
管程进程不断地从请求管程中读取对过程调用的请求,对每一个请求,它都要调用以独立线程存在的相应处理程序。
这种线程可以使用c.wait操作阻塞自己和c.signal 操作去唤醒其他线程。
当线程终止时,管程进程将通过向应答管道写入信息,把结果返回给原先的调用进程。
(2)将临界区问题扩展到多于两个进程的情况。
使用并比较两种解决方法:Pthreads提供的构造和纯软件方案。