同步与互斥实例
操作系统第6章 进程互斥与同步
Co-begin void Producer_i( ) (i=1,2…k) { item next_p; while(1){ produce an item in next_p P(empty); P(s); add next_p to buffer V(s); V(full); } } void consumer_j( ) (j=1,2…m) { item next_c; while(1){ P(full); P(s); remove an item from buffer to next_c V(s); V(empty); consume the item in next_c}} Co-end
• 进入临界段之前要申请,获得批准方可进入; • 退出临界段之后要声明,以便其他进程进入。
用程序描述: While(1){ entry_section; critical_section; exit_section; remainder_section; }
解决临界段问题的软件算法必须遵循:
准则1:不能虚设硬件指令或假设处理机数目。 准则2:不能假设n个进程的相对速度。 准则3:当一个进程未处于其临界段时,不应阻止 其他进程进入临界段。 准则4:当若干进程欲进入临界段时,应在有限时 间内选出一个进程进入其临界段。 用准则3,4不难推出下面原则 协调各进程入临界段的调度原则: • 当无进程处于临界段时,允许一个进程立即进入临界段。
3.实现临界段的硬件方法
利用处理机提供的特殊指令实现临界区加锁。 常见硬件指令有: ⑴ “Test_and_Set”指令 该指令功能描述为: int *target ( 限定为0,1) int Test_and_Set (int *target) { int temp; temp = *target ; *target = 1; return temp; }
同步与互斥例题
1、有一个东西方向的独木桥,如下图所示,每次只能有一个通过,且不允许人在桥上停留。
东、西两端各有若干人在等待过桥。
请用P、V操作来实现东西两端人过桥的问题。
解:设bridge代表独木桥这一临界资源,初值为1。
东西两边的人用进程表示;其中P east i(i=1,2,…,n)代表东边的人的进程;P west i(i=1,2,…,n)代表西边的人的进程。
现用P、V操作实现东西两端人过桥问题描述如下:semaphore brigde=1;main(){cobegin{P east i(i=1,2,…,n)while (true) {p(bridge);从东向西过桥;v(bridge); }P west i(i=1,2,…,n)while (true){p(bridge);从西向东过桥;v(bridge); }} coend }2、对于生产者—消费者问题,若缓冲区单元中有一个,生产者和消费者只有一个,如图所示。
用P、V原语实现生产者和消费者的操作。
解:此是典型的同步问题。
设置两个信号量,bufferempty为生产者的私有信号量,初值为1,代表最初可用的空单元数;bufferfull为消费者的私有信号量,初值为0,代表最初可消费的产品个数;producer 代表生产者进程,consumer代表消费者进程。
现将用P、V实现此生产者和消费者问题的控制描述如下:semaphore bufferempty=1;semaphore bufferfull=0;main(){cobegin{procedurewhile(true){p(bufferempty);送产品至缓冲区;v(bufferfull);}consumerwhile(true){p(bufferfull);从缓冲区中取走产品;v(bufferempty);}} coend}。
进程同步与互斥应用例子
数据库
写者 { 写数据库; }
读者 { 读数据库; }
进程的互斥
分析:写进程writer、读进程reader因竞争数据库这个资源
而成为互斥关系。因为写进程执行时,不能执行其他读写 进程,所以还必须设置一个计数器统计读进程的个数。如 果是第一个读进程,就与写进程竞争数据库。如果是最后 一个读进程,就释放数据库。因计数器是一个临界资源, 所以多个读进程对计数器的操作又是互斥操作。
进程的同步
解:这是一个同步问题,信号量初值:S2=0,S3=0,S4=0, S5=0,S6=0
进程P1 执行P1 V(S2) V(S3) 进程P4 P(S4) 执行P4 V(S6) 进程P2 P(S2) 执行P2 V(S4) 进程P5 P(S5) 执行P5 V(S6) 进程P3 P(S3) 执行P3 V(S5) 进程P6 P(S6) P(S6) 执行P6
进程的同步
• 例1:假设有三个并发进程P,Q,R,其中P负责从输入设 备上读入信息并传送给Q,Q将信息加工后传送给R,R则负 责将信息打印输出。进程P、Q共享一个缓冲区,进程Q、R 共享另一个缓冲区。
3个进程P、Q、R P进程: 从输入设备上读入信息 将信息放入缓冲区1 Q进程: 从缓冲区1取出信息 将信息放入缓冲区2中 R进程: 从缓冲区2取出信息 将信息打印输出
进程的互斥
练习:过十字路口(单道)。
P4
P1
P3
P2
P1 { 通过路口; }
P2 { 通过路口; }
P3 { 通过路口; }
P4
{ 通过路口; }
进程的互斥
分析:进程P1、P2、P3、P4因竞争十字路口这个资源而成 为互斥关系。 设:信号量m表示十字路口资源,初值为1表示资源可用。
第三章同步和互斥
T2: ... R ead( x) ; i f x>=1 t hen x: =x- 1; w i t e( x) ; r
get
copy
put
f
s
t
g
有3个进程:get, copy和put,它们对4个存储区域f、s、t和g进 行操作。
操作顺序冲突
f 初始状态 g,c,p g,p,c c,g,p c,p,g p,c,g p,g,c 3,4,...,m 4,5,...,m 4,5,...,m 4,5,...,m 4,5,...,m 4,5,...,m 4,5,...,m
– 信号量只能通过初始化和两个标准的原语来访问 --作为OS核心代码执行,不受进程调度的打断 – 初始化指定一个非负整数值,表示空闲资源总数 (又称为"资源信号量")--若为非负值表示当前 的空闲资源数,若为负值其绝对值表示当前等待 临界区的进程数
• "二进制信号量(binary semaphore)":只允许信 号量取0或1值
算法2:双标志、先检查
while (flag[j]); flag[i] = TRUE; critical section flag[i] = FALSE; remainder section
<a> <b>
• 设立一个标志数组flag[]:描述进程是否在 临界区,初值均为FALSE。
– 先检查,后修改:在进入区检查另一个进程是 否在临界区,不在时修改本进程在临界区的标 志; – 在退出区修改本进程在临界区的标志;
P,V操作的“忙等待”执行方式
• P(S): • V(S): While S<=0 do skip; S:=S-1; S:=S+1;
同步与互斥实现方法
同步与互斥实现方法同步与互斥是并发编程中重要的概念,用于解决多个线程访问共享资源的问题。
同步是指多个线程按照一定的顺序执行,以避免产生竞争条件和数据不一致的问题;而互斥是指多个线程不能同时访问一些共享资源,而需要按照一定的顺序进行访问。
下面将介绍几种常见的同步与互斥实现方法。
1. 互斥锁(Mutex)互斥锁是最常见和最基本的同步与互斥机制。
互斥锁提供了两个操作,即上锁(lock)和解锁(unlock)。
一个线程在执行临界区代码时会上锁,其他线程在发现互斥锁已经被锁定时,则需要等待。
直到执行完临界区代码后,线程解锁,其他线程才能继续执行。
互斥锁的实现可以是通过硬件原子指令或通过操作系统的系统调用进行。
2. 信号量(Semaphore)信号量是另一种常见的同步与互斥机制。
信号量有一个计数器,用来表示资源的可用数量。
一个线程在访问共享资源之前需要申请信号量,如果信号量的计数器大于零,说明资源可用,线程可以继续执行;如果计数器等于零,说明资源不可用,线程需要等待。
当线程使用完共享资源后,需要释放信号量,使得其他线程可以继续申请资源。
3. 读写锁(ReadWrite Lock)读写锁是用于读写操作频繁且对数据一致性要求较高的情况下,提高并发性能的一种同步与互斥机制。
读写锁分为两种锁,即读锁和写锁。
多个线程可以同时持有读锁来读取共享资源,但是只有一个线程可以持有写锁进行写操作。
当存在写锁时,其他线程无法获得读锁或写锁。
4. 条件变量(Condition Variable)条件变量用于等待一些条件的成立或通知一些条件的变化。
线程可以通过条件变量等待一些条件的成立,当条件成立时,线程被唤醒并继续执行。
条件变量通常与互斥锁一起使用,以保证在等待条件时不会产生竞态条件。
5. 屏障(Barrier)屏障用于将一个线程组分成多个阶段,并在每个阶段结束时进行同步。
当每个线程到达屏障时,会被阻塞直到所有线程到达,然后同时开始下一个阶段的执行。
同步与互斥问题解决方案--例题
写者: While(true){
P(w); 写 V题: 写者优先 条件: 1)多个读者可以同时进行读 2)写者必须互斥(只允许一个写者写,也 不能读者写者同时进行) 3)写者优先于读者(一旦有写者,则后续 读者必须等待,唤醒时优先考虑写者)
readcount=0; writecount=0; S=mutex=w=wmutex=1 读者: while (true) { P(S); P(mutex); readcount ++; if (readcount==1) P (w); V(mutex); V(S); 写者: while (true) { P(wmutex); writecount++; if(writecount==1) P(S); V(wmutex); P(w); 写 V(w); P(wmutex); writecount--; if(writecount=0) V(S); V(wmutex); };
读
P(mutex); readcount --; if (readcount==0) V(w); V(mutex);
继续
• 在实际应用中,写优先非常重要,因为写 代表的是对数据的更新。而我们希望读到 的是最新的消息。因此继续进行改进,就 要考虑,如果写者到来,可以让正在读的 读者让路,先让写者写。
– 无读者、写者,新读者可以读 – 有写者等待,但有其他读者正在读,新读者可以读 – 有写者写,新读者等
• 如果写者来:
– 无读者,新写者可以写 – 有读者,新写者等待 – 有其他写者,新写者等待
读者: While(true){ P(mutex); readcount++; if(readcount==1) P(w); V(mutex); 读 P(mutex); readcount--; if(readcount==0) V(w); V(mutex); }
操作系统进程互斥与同步-互斥
35
互斥问题举例4
某车站售票厅有20个窗口,任何时刻最多可容纳20 名购票者进入,当售票厅中少于20名购票者时,则厅 外的购票者可立即进入,否则需在厅外等待。若把一 个购票者看作一个进程,请用P、V操作管理这些并发 进程,要求如下:
⑴.在主函数中给出信号量的定义和初值。
⑵.给出一个购票者进程的算法。
2. 用信号灯的P、V操作实现互斥
框图描述
设:mutex为互斥信号灯,初值为1。
进程 pa p(mutex) 进程 pb p(mutex)
进入临界区csa
进入临界区csb
v(mutex)
v(mutex)
48
程序描述
程序 task2
main( )
{ int mutex=1; cobegin pa( ); pb( ); coend ∕* 互斥信号灯 *∕
⑶.给出当购票者最多不超过n (设n>20)个时,信
号量可能的变化范围。
36
算法描述 ⑴.主函数算法: main() { int mutex=20; cobegin P1(); „Pi();„Pn(); coend } ⑵.购票者i的算法: Pi() { P(mutex); 购票; V(mutex); }
45
V 操作的实现
入口 S+1 → S >0 S≤0 ?
从信号灯的等待队列中取出首元素
入就绪队列Leabharlann 置“就绪状态”返回
PV操作是通过原语实现的
4.6 进程互斥的实现
1. 用上锁原语和开锁原语实现进程互斥
框图描述
进程 pa 进程 pb
上锁原语
上锁原语
进入临界区csa
互斥和同步
正常运行
到站停
售票
开门
UNTIL FALSE
UNTIL FALSE
3 临界区问题
临界区(critical section):进程中 访问临界资源的一段代码。 进入区(entry section):在进入临 界区之前,检查可否进入临界区 的一段代码。如果可以进入临界 区,通常设置相应"正在访问临界 区"标志 退出区(exit section):用于将"正 在访问临界区"标志清除。 剩余区(remainder section):代 码中的其余部分。
设立一个标志数组flag[]:描述进程是否在临界区,初值均 为FALSE,它是进程到达临界区的钥匙 先检查,后修改:在进入区中,检查另一个进程是否在临 界区,不在临界区时修改本进程在临界区的标志; 在退出区修改本进程在临界区的标志;
<a> <b>
<a> <b>
Dekker算法-尝试2:双标志、先检查
容易造成资源利用不充分:在Pi出让临界区之后,Pj使用
临界区之前,Pi不可能再次使用临界区;
如果一个进程失败了,另一个进程将被永久阻塞
忙等待
(busy waiting) : 为了等待一事件的发生, 重复执 行一段循环代码 ---- 白白消耗CPU时间
Dekker算法-尝试2:双标志、先检查
分析:产生错误的原因是不加控制地访问共享变量x
1 并发的原理-- -示例
与进程的执行顺序有关的错误
复制一个记录
Cobegin get; copy; put; Coend
get
copy
put
f
源记录
同步与互斥实例
(2)每个进程每次只拣一个子,当一个进程在 拣子时不允许另一进程去拣子;
(3)当一个进程拣了一个子(黑或白)以后, 必让另一个进程拣一个子(黑或白) 。
请用P、V操作管理两个并发进程,使其能正 确实现上述功能。
Var S1, S2: semaphore:=1,0;
理发师问题理发师问题l理发店里有一位理发师一把理发椅和n把供等候理发的顾客坐的椅子l如果没有顾客理发师便在理发椅上睡觉l一个顾客到来时它必须叫醒理发师l如果理发师
进程同步与互斥实例
同步实例
1.经典的生产者─消费者问题
生产者
消费者
1.经典的生产者─消费者问题
var B : integer;
empty:semaphore; /* 可以使用的空缓冲区数 */
process 小和尚: begin repeat P(empty); P(count); P(mutex1); 从井中取水; V(mutex1); P(mutex2); 送水入水缸; V(mutex2); V(count); V(full); until false;
end
Var mutex1, mutex2, empty, full, count: semaphore;
④在每个进程中用于实现互斥的PV操作必须成对出现;用于实现 同步的PV操作也必须成对出现,但可以分别出现在不同的进程中; 在某个进程中如果同时存在互斥与同步的P操作,则其顺序不能颠 倒,必须先执行对同步信号量的P操作,再执行对互斥信号量的P 操作,但V操作的顺序没有严格要求。
同步与互斥的解题步骤
full:semaphore;
/* 缓冲区内可以使用的产品数 */
empty := 1;
进程同步与互斥问题
p1() {
while(1) {
洗桔子; P(m1) ; 放桔子; V(m3) ; } }
p2() {
while(1) {
洗苹果 ; P(m1); 放苹果; V(m2); } }
p3() {
while(1) {
P(m2) ; 取苹果; V(m1); 吃苹果;
} }
p4() {
while(1) {
P(m3) ; 取桔子; V(m1); 吃桔子;
p3() {
while(1) {
P(m2) ; 取水果; V(m1); 吃水果;
} }
进程的同步
分析:父母亲先放水果,儿子再取水果吃;父亲与儿子,母 亲与儿子是一个同步关系,父亲与母亲要竞争空盘子。
解法二:设信号量m1表示父亲或母亲放完水果,信号量m2 表示儿子取完水果。
int m1=0,m2=1; cobegin
放水果; }
吃桔子; }
吃苹果; }
进程的同步
分析:父亲先放水果,儿子女儿再吃水果;儿子女儿取完水 果,父亲再放水果,这三个进程是一个同步关系。
解法一:设信号量m1表示父亲能否放水果,m2表示儿子能 否取桔子,m3表示女儿能否取苹果。
int m1=1,m2=0,m3=0;
cobegin
p1() // p2() // p3()
} }
例3-4:吃水果。 父亲 母亲
进程的同步
女儿 桔 苹0子 果
儿子
父亲 P1 while(true) {
洗桔子;
母亲 P2 while (true) {
洗苹果;
放桔子; }
放苹果; }
儿子 P3 while(true) {
取苹果;
实验四-同步与互斥-Linux实验报告
实验四-同步与互斥-Linux实验报告实验四同步与互斥 Linux 实验报告一、实验目的本次实验旨在深入理解操作系统中进程的同步与互斥概念,通过在Linux 环境下进行编程实践,掌握相关的实现方法和技术,提高对并发控制的认识和应用能力。
二、实验环境操作系统:Linux(Ubuntu 2004)编程语言:C 语言开发工具:GCC 编译器三、实验原理(一)同步同步是指多个进程在执行过程中需要按照一定的顺序协调工作,以确保它们之间的操作具有正确的逻辑关系。
常见的同步机制包括信号量、条件变量等。
(二)互斥互斥是指在同一时刻,只允许一个进程访问共享资源,以避免多个进程同时操作导致的数据不一致或错误。
实现互斥的常见方法有互斥锁、临界区等。
四、实验内容(一)使用信号量实现生产者消费者问题1、问题描述生产者不断生产产品并放入缓冲区,消费者从缓冲区取出产品进行消费。
缓冲区大小有限,当缓冲区满时生产者停止生产,当缓冲区为空时消费者停止消费。
2、实现思路创建一个信号量来表示缓冲区的可用空间数量,另一个信号量表示缓冲区中已有的产品数量。
生产者在生产前检查可用空间信号量,消费者在消费前检查产品数量信号量。
3、代码实现```cinclude <stdioh>include <stdlibh>include <pthreadh>include <semaphoreh>define BUFFER_SIZE 5int bufferBUFFER_SIZE;int in = 0;int out = 0;sem_t empty_sem;sem_t full_sem;pthread_mutex_t mutex;void producer(void arg) {int item;while (1) {item = rand()% 100;sem_wait(&empty_sem);pthread_mutex_lock(&mutex);bufferin = item;printf("Producer: Produced item %d at position %d\n", item, in);in =(in + 1) % BUFFER_SIZE;pthread_mutex_unlock(&mutex);sem_post(&full_sem);}return NULL;}void consumer(void arg) {int item;while (1) {sem_wait(&full_sem);pthread_mutex_lock(&mutex);item = bufferout;printf("Consumer: Consumed item %d from position %d\n", item, out);out =(out + 1) % BUFFER_SIZE;pthread_mutex_unlock(&mutex);sem_post(&empty_sem);}return NULL;}int main(){pthread_t producer_thread, consumer_thread;sem_init(&empty_sem, 0, BUFFER_SIZE);sem_init(&full_sem, 0, 0);pthread_mutex_init(&mutex, NULL);pthread_create(&producer_thread, NULL, producer, NULL);pthread_create(&consumer_thread, NULL, consumer, NULL);pthread_join(producer_thread, NULL);pthread_join(consumer_thread, NULL);sem_destroy(&empty_sem);sem_destroy(&full_sem);pthread_mutex_destroy(&mutex);return 0;}```(二)使用互斥锁实现读者写者问题1、问题描述存在多个读者和一个写者,读者可以同时读取数据,但写者在写数据时不允许有其他读者或写者访问。
同步与互斥实例
Var S, mutex1, mutex2: semaphore; S:=100; mutex1:=1; mutex2:=1
process Pi: begin P(S); P(mutex1); 进入口处,取一只篮子; V(mutex1); 选购商品; P(mutex2); 结账,并归还篮子; V(mutex2); V(S);
各进程的代码如下 :
进程A
进程B
进程C
...
…
...
...
…
...
P(mutex)
P(mutex)
P(mutex)
申请打印机
申请打印机 申请打印机
使用打印机
使用打印机 使用打印机
V(mutex)
V(mutex) V(mutex)
购物问题。某超级市场,可容纳100个人同时 购物,入口处备有篮子,每个购物者可持一个 篮子入内购物。出口处结账,并归还篮子(出、 入口仅容纳一人通过)。请用P、V操作完成 购物同步算法。
Var S, S1, S2: semaphore;
process (E-W)i: begin P(S1); rc1:=rc1+1; if rc1=1 then P(S); V(S1); 过桥;
P(S1);
rc1,rc2: integer; S, S1, S2:=1; rc1,rc2:=0;
process (W-E)j: begin P(S2); rc2:=rc2+1; if rc2=1 then P(S); V(S2); 过桥;
full := 0;
/* 缓冲区内没有产品 */
cobegin /*多个子进程并发执行函数*/
Process producer
C语言同步与互斥技术
C语言同步与互斥技术在多线程编程中,同步与互斥是非常重要的概念。
同步指的是协调多个线程之间的执行顺序,而互斥则是为了保护共享资源,避免多个线程同时访问造成数据不一致的问题。
C语言提供了一些同步与互斥技术的函数和机制,本文将介绍其中的几种常用的方法。
1. 互斥锁互斥锁是最常见的同步机制之一。
它的作用是确保同一时间只有一个线程可以访问被保护的资源。
在C语言中,可以使用互斥锁来实现对临界区的访问控制。
互斥锁的使用通常分为两个步骤:初始化和加锁。
下面是互斥锁的示例代码:```#include <pthread.h>pthread_mutex_t mutex;int main() {// 初始化互斥锁pthread_mutex_init(&mutex, NULL);// 加锁pthread_mutex_lock(&mutex);// 临界区操作// 解锁pthread_mutex_unlock(&mutex);// 销毁互斥锁pthread_mutex_destroy(&mutex);return 0;}```2. 信号量信号量是一种更为通用的同步与互斥工具。
它可以用于控制对资源的访问,也可以用于线程之间的通信。
C语言中提供了信号量的相关函数,如sem_init、sem_wait和sem_post等。
下面是信号量的示例代码:```#include <semaphore.h>sem_t semaphore;void* thread_function(void* arg) {while (1) {// 等待信号量sem_wait(&semaphore);// 临界区操作// 发送信号量sem_post(&semaphore);}}int main() {// 初始化信号量sem_init(&semaphore, 0, 1);// 创建线程pthread_t thread;pthread_create(&thread, NULL, thread_function, NULL); // 主线程操作// 销毁信号量sem_destroy(&semaphore);return 0;}```3. 条件变量条件变量通过线程之间的等待与唤醒机制实现同步与互斥。
进程互斥与同步实例
三个进程R、W1、W2共享一缓冲器B, 而B中一次只能存放一个数。R将从输入设 备上读入的数放到缓冲器B中。若存放的是 奇数,则允许W1将其取出打印,如果是偶 数,由进程W2取出打印。
W1
R
B
W2
Begin B:integer; S,SO,SE:semaphore; S:=1;SO:=0,SE:=0; Cobegin Process R x:integer; begin L1:从输入设备读入一个数; x:=读入的数; P(S) B:=x; if (B/2 !=0) then V(SO) else V(SE); goto L1 end;
从右至左:
P(S2); Counter2++; If conter2= =1 then P(S) V(S2); 过桥; P(S2) Counter2--; If conter2= =0 then V(S) V(S2);
桌上有一只盘子,每次只能放入一只水 果;爸爸专向盘子中放苹果(apple),妈妈 专向盘子中放桔子(orange),儿子专等吃盘 子中的桔子,女儿专等吃盘子里的苹果。
ቤተ መጻሕፍቲ ባይዱ
plate : integer; sp:semaphore /* 盘子里可以放几个水果 */ sg1:semaphore; /* 盘子里有桔子 */ sg2:semaphore; /* 盘子里有苹果 */ sp := 1; /* 盘子里允许放一个水果*/ sg1:= 0; /* 盘子里没有桔子 */ sg2:= 0; /* 盘子里没有苹果*/
Process W1 y:=integer; begin L2:P(SO) y:=B; V(S); print y; go to L2 end
C语言并发编程线程同步和互斥
C语言并发编程线程同步和互斥在并发编程中,线程同步和互斥是非常重要的概念。
当多个线程同时访问共享资源时,如果没有合适的同步机制,就会产生竞态条件(Race Condition)问题,导致程序的执行结果不确定或出现错误。
因此,掌握线程同步和互斥的方法对于编写高效可靠的并发程序至关重要。
1. 互斥锁(Mutex)互斥锁是一种最常见的线程同步机制,通过对临界资源加锁,确保同一时间只有一个线程能够访问该资源。
C语言中可以使用互斥锁来实现线程的互斥访问。
以下是互斥锁的使用示例:```c#include <pthread.h>pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;void* thread_function(void* arg) {// 在访问共享资源之前加锁pthread_mutex_lock(&mutex);// 访问共享资源// 在访问共享资源之后解锁pthread_mutex_unlock(&mutex);return NULL;}```2. 条件变量(Condition Variable)条件变量是一种线程同步机制,用于线程之间的通信和协调。
通过条件变量,一个线程可以等待某个条件的满足,而另外一个线程满足这个条件后就通过条件变量发出通知。
以下是条件变量的使用示例:```c#include <pthread.h>pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;pthread_cond_t cond = PTHREAD_COND_INITIALIZER;void* thread_function(void* arg) {// 在访问共享资源之前加锁pthread_mutex_lock(&mutex);// 判断条件,如果条件不满足,则等待while (!condition) {pthread_cond_wait(&cond, &mutex);}// 条件满足后,访问共享资源// 在访问共享资源之后解锁pthread_mutex_unlock(&mutex);return NULL;}void update_condition() {// 更新条件// 发出条件满足的信号pthread_cond_signal(&cond);}```3. 信号量(Semaphore)信号量是一种常用的线程同步机制,用于控制同时访问某个共享资源的线程数量。
进程互斥和同步举例73页PPT
谢谢!
36、自己的鞋子,自己知道紧在哪里。——西班牙
37、我们唯一不会改正的缺点是软弱。——拉罗什福科
xiexie! 38、我这个人走得很慢,但是我从不后退。——亚伯拉罕·林肯
进程互斥和同步举例
1、纪律是管理关系的形式。——阿法 纳西耶 夫 2、改革如果不讲纪律,就难以成功。
3、道德行为训练,不是通过语言影响 ,而是 让儿童 练习良 好道德 行为, 克服懒 惰、轻 率、不 守纪律 、颓废 等不良 行为。 4、学校没有纪律便如磨房里没有水。 ——夸 美纽斯
5、教导儿童服从真理、服从集体,养 成儿童 自觉的 纪律性 ,这是 儿童道 德教育 最重要 的部分 。—— 陈鹤琴
39、勿问成功的秘诀为何,且尽全力做你应该做的事吧。——美华纳
40、学而不思则罔,思而不学则殆。——孔子
ห้องสมุดไป่ตู้
操作系统实验五线程间的互斥与同步
三,实验要求
按照要求编写程序,放在相应的目录中,编译成功后执行,并按 照要求分析执行结果,并写出实验报告。
四,实验设计
1,功能设计 根据实验要求,主程序需要创建四个线程,两个线程负责从文件
读取数据到缓冲区, 两个线程负责将缓冲区的数据做数学运算。 由于 同一个进程中的各个线程共享资源, 可以用一个二维数组的全局变量 作为公共缓冲区, 同时还需要一个整形全局变量 size 用来做数组的索 引。读线程的运行函数打开不同的文件并从中读取数据到二维数组 中,每次写入数组后 size 加一。运算线程从二维数组中读数并做运算, 每次读数之前 size 减一。本题的关键在于如何使用信号量保证进程的 同步与互斥。 在运算线程从缓冲区读取之前缓冲区里必须有数, 即任 意时刻运算操作的执行次数必须小于等于读取操作的执行次数。 同时 应该保证两个读线程和两个运算线程两两互斥。 由于以上分析, 使用 了四个信号量 sem1,sem2,sem3 和 sem4。sem1保证线程 1 和线程 2 互斥, sem2 保证线程 3 和线程 4 互斥, sem3 保证线程 3 和线程 4 互斥, sem4 保证线程 4 和线程 1 互斥。即这四个信号量使四个线程 循环进行,从而保证了运行结果的正确性。 源代码及注释:
while(!feof(fp)){
sem_wait(&sem2);
//减少信号量 sem2
if(!fscanf(fp,"%d %d",&stack[size][0],&stack[size][1]))return;
size++;
//读两个数到公共缓冲区
sem_post(&sem3);
//增加信号量 sem3
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
提水入缸供老和尚饮用。水缸可以容纳10桶水,
水取自同一井水。水井狭窄,每次只能容一个
桶取水。水桶总数为 3 个。每次入、出水缸仅
一桶,且不可同时进行。试给出有关取水、入 水的算法描述。
process 小和尚: begin repeat P(empty); P(count); P(mutex1); 从井中取水;
V(mutex1);
P(mutex2); 送水入水缸;
V(mutex2);
V(count); V(full);
until false;
end
V(count);
until false;
习题
1.司机和售票员问题 问题描述: 在公共汽车上,司机和售票员的活动分别是: 司机的活动: 启动车辆 正常运行 到站停车 售票员的活动: 关车门 售票 开车门 在汽车不断的到站,停车,行驶过程中,这两个活动有 什么同步关系?用信号量和P,V操作实现.
Var S, S1, S2: semaphore; process (E-W)i: begin P(S1);
rc1,rc2: integer;
S, S1, S2:=1; rc1,rc2:=0;
process (W-E)j: begin
P(S2);
rc2:=rc2+1; if rc2=1 then P(S);
同步与互斥的解题思路
①分清哪些是互斥问题(互斥访问临界资源的),哪些是同步问 题(具有前后执行顺序要求的)。 ②对互斥问题要设置互斥信号量,不管有互斥关系的进程有几个 或几类,通常只设置一个互斥信号量,且初值为1,代表一次只允 许一个进程对临界资源访问。 ③对同步问题要设置同步信号量,通常同步信号量的个数与参与 同步的进程种类有关,即同步关系涉及几类进程,就有几个同步 信号量。同步信号量表示该进程是否可以开始或该进程是否已经 结束。 ④在每个进程中用于实现互斥的PV操作必须成对出现;用于实现 同步的PV操作也必须成对出现,但可以分别出现在不同的进程中; 在某个进程中如果同时存在互斥与同步的P操作,则其顺序不能颠 倒,必须先执行对同步信号量的P操作,再执行对互斥信号量的P 操作,00个人同时 购物,入口处备有篮子,每个购物者可持一个 篮子入内购物。出口处结账,并归还篮子(出、 入口仅容纳一人通过)。请用P、V操作完成 购物同步算法。
Var S, mutex1, mutex2: semaphore;
S:=100; mutex1:=1; mutex2:=1 process Pi:
rc1:=rc1+1;
if rc1=1 then P(S); V(S1);
V(S2);
过桥; P(S2);
过桥;
P(S1); rc1:=rc1-1; if rc1=0 then V(S); V(S1); end
rc2:=rc2-1;
if rc2=0 then V(S);
V(S2);
end
(1) A、B、C三个进程之间存在互斥的制约关系。因 为打印机属于临界资源,必须一个进程使用完之后另 一个进程才能使用。 (2)mutex:用于互斥的信号量,初值为1。 各进程的代码如下 : 进程A 进程B 进程C ... … ... ... … ... P(mutex) P(mutex) P(mutex) 申请打印机 申请打印机 申请打印机 使用打印机 使用打印机 使用打印机 V(mutex) V(mutex) V(mutex)
2.实例
设某台机挂有两个I/O通道:分别挂一 台输入机和一台打印机。卡片机上有 一叠数据卡片,现在要把这些数据逐 一输入到缓冲区 B1 ,然后再复制到缓 冲区B2,并在打印机上打印出来。 问:系统可设哪些进程来完成这个任 务?用P-V原语写这些进程的同步算法。
解:由上图可见,系统可设 3 个进程:输入进程、复制进 程、打印进程;分别用进程R、进程C、进程P来表示。 这些进程之间的相互制约关系: R受C的约束;C受R、P的约束;P受C的约束。 设4个信号量:S1=1,S2=0,S3=1,S4=0 同步算法如下:
互斥实例
有三个用户进程A、B和C,在运行过程中都要使 用系统中的一台打印机输出计算结果。 试说明A、B、C进程之间存在什么样的制约关 系? 为保证这三个进程能正确地打印出各自的结果, 请用信号量和P、V操作写出各自的有关申请、 使用打印机的代码。要求给出信号量的含义和 初值。
2.吸烟者问题 三个吸烟者在一间房间内,还有一个香烟 供应者。为了制造并抽掉香烟,每个吸烟者需 要三样东西:烟草、纸和火柴。供应者有丰富 的货物提供。三个吸烟者中,第一个有自己的 烟草,第二个有自己的纸,第三个有自己的火 柴。供应者将两样东西放在桌子上,允许一个 吸烟者进行对健康不利的吸烟。当吸烟者完成 吸烟后唤醒供应者,供应者再放两样东西(随 机地)在桌面上,然后唤醒另一个吸烟者。试 为吸烟者和供应者采用信号量机制解决问题。
3.理发师问题
理发店里有一位理发师、一把理发椅和 n 把供
等候理发的顾客坐的椅子
如果没有顾客,理发师便在理发椅上睡觉
一个顾客到来时,它必须叫醒理发师
如果理发师正在理发时又有顾客来到,则如果
有空椅子可坐,就坐下来等待,否则就离开
记 录 型 信 号 量 解 决 理 发 师 问 题
var waiting : integer; /*等候理发的顾客数*/ CHAIRS:integer; /*为顾客准备的椅子数*/ customers, barbers,mutex : semaphore; customers := 0; barbers := 0; waiting := 0; mutex := 1; Process barber; begin while(TRUE); /*理完一人,还有顾客吗?*/ P(cutomers); /*若无顾客,理发师睡眠*/ P(mutex); /*进程互斥*/ waiting := waiting – 1; /*等候顾客数少一个*/ V(barbers); /*理发师去为一个顾客理发*/ V(mutex); /*开放临界区*/ cut-hair( ); /*正在理发*/ end; process customer begin P(mutex); /*进程互斥*/ if waiting<CHAIRS begin /*看看有没有空椅子*/ waiting := waiting+1; /* 等候顾客数加1*/ V(customers); /*必要的话唤醒理发师*/ V(mutex); /*开放临界区*/ P(barbers); /*无理发师, 顾客坐着养神*/ get-haircut( ); /*一个顾客坐下等理发*/ end V(mutex); /*人满了,走吧!*/ end;
拣棋子问题。生产围棋的工人不小心把相等数 量的黑棋子和白棋混装在一个箱子里,先要用 自动分拣系统把黑棋子和白棋子分开,该系统 由两个并发执行的进程组成,系统功能如下: (1)进程A专门拣黑子,进程B专门拣白子; (2)每个进程每次只拣一个子,当一个进程在 拣子时不允许另一进程去拣子; (3)当一个进程拣了一个子(黑或白)以后, 必让另一个进程拣一个子(黑或白) 。 请用P、V操作管理两个并发进程,使其能正 确实现上述功能。
同步与互斥的解题步骤
( 1 )确定进程。包括进程的数量、进程的工 作内容,可以用流程图描述。 ( 2 )确定同步互斥关系。根据是否使用的是 临界资源,还是处理的前后关系,确定同步与 互斥,然后确定信号量的个数、含义,以及对 信号量的P、V操作。 (3)用类C语言描述同步或互斥算法。
Var mutex: semaphore;
process (E-W)i:
process (W-E)j: begin P(mutex); 过桥; V(mutex); end
begin
P(mutex); 过桥; V(mutex); end
.独木桥问题。某条河上只有一座独木桥,以 便行人过河。现在河的两边都有人要过桥,按 照下面的规则过桥。为了保证过桥安全,请用 P、V操作分别实现正确的管理。 过桥的规则是:同一方向的可连续过桥, 某方向有人过桥时另一方向的人要等待。
进程同步与互斥实例
同步实例
1.经典的生产者─消费者问题
生产者 消费者
1.经典的生产者─消费者问题
var B : integer; empty:semaphore; /* 可以使用的空缓冲区数 */ full:semaphore; /* 缓冲区内可以使用的产品数 */ empty := 1; /* 缓冲区内允许放入一件产品 */ full := 0; /* 缓冲区内没有产品 */ cobegin /*多个子进程并发执行函数*/ Process producer process consumer begin begin L1: L2: Produce a product; P(full); P(empty); 取产品 直到取为空 放产品; 直到为满; V(empty); V(full); Consume a product; Goto L1; Goto L2; end; end; coend
Var S1, S2: semaphore:=1,0; process A:
process B:
begin
repeat P(S1);
begin
repeat P(S2); 拣白子; V(S1); until false end
拣黑子;
V(S2); until false; end
某寺庙有小、老和尚若干,有一水缸,由小和尚
Var mutex1, mutex2, empty, full, count: semaphore; mutex1:=1; mutex2:=1; empty:=10; full:=0; count:=3;