DJ2-4 进程同步(第二节课)
创始人
2025-06-01 04:39:05
0

目录

2.4.3 信号量机制

1. 整型信号量

2. 记录型信号量

3. AND 型信号量

4. 信号量集

三种特例

2.4.4 信号量的应用

1. 利用信号量实现进程互斥

2. 利用信号量实现前趋关系

2.4.5 管程机制

1. 管程的组成

2. 管程的主要特点


2.4.3 信号量机制

信号量(Semaphores)机制:是一种卓有成效的进程同步工具。

1. 整型信号量

把整型信号量定义为一个用于表示资源数目的整型量 S,仅能通过两个标准的原子操作 wait(S) 和 signal(S) 来访问。这两个原子操作又分别被称为 P 和 V 操作,注意必须使用大写。

wait(S) {while(S <= 0);  //do no-op,CPU空转S--;            //访问资源,资源减一
}signal(S) {S++;            //释放资源,资源加一
}

在 wait(S) 中,对 S 值的测试和做 S=S-1 操作时都是不可中断的。

2. 记录型信号量

整型信号量的问题:忙等,即当 wait(S) 中信号量 S<=0 时,会不停地进行测试,因此未遵循让权等待的原则。而记录型信号量机制则是一种不存在 “忙等” 现象的进程同步机制。

记录型信号量的数据结构可描述如下:

typedef struct {int value;struct process_control_block * list;
} semaphore;

原子操作 wait(S) 和 signal(S) 可描述如下:

wait(semaphore * S) {S->value--;if(S->value < 0) block(S->list);//S->value == 0时代表刚好取走最后一个资源
}signal(semaphore * S) {S->value++;if(S->value <= 0) wakeup(S->list);//S->value == 0时代表刚好还有一个进程被阻塞
}

整型信号量和记录型信号量的问题:

  • 只能有效地解决多个进程共享一种临界资源的情况
  • 即只需要设置一个临界区

下面来看多个进程需要访问多种临界资源的情况。假设进程 A 和 B 需要访问共享数据 D 和 E,设置互斥型信号量 Dmutex 和 Emutex,两者初始值均为 1,进程 A 和 B 的访问操作如下:

process A:         |process B:
wait(Dmutex);      |wait(Emutex);
wait(Emutex);      |wait(Dmutex);
signal(Emutex);    |signal(Dmutex);
signal(Dmutex);    |signal(Emutex);

若进程 A 和 B 按下述次序交替执行 wait 操作:

process A: wait(Dmutex);    //Dmutex=0
process B: wait(Emutex);    //Emutex=0
process A: wait(Emutex);    //Emutex=-1, A blocked
process B: wait(Dmutex);    //Dmutex=-1, B blocked

进程阻塞以后也不能释放已持有的资源。最后,进程 A 和 B 就将处于僵持状态。在无外力作用下,两者都将无法从僵持状态中解脱出来。我们称此时的进程 A 和 B 已进入死锁状态。

3. AND 型信号量

AND 同步机制的基本思想:将进程在整个运行过程中需要的所有资源,一次性全都地分配给进程,待进程使用完后再一起释放。只要尚有一个资源未能分配给进程,其它所有可能为之分配的资源也不分配给它。

对若干个临界资源的分配采取原子操作:要么把它所请求的资源全部分配到进程,要么一个也不分配。具体方法是在 wait 操作中,增加了一个 “AND” 条件,故称为 AND 同步,或称为同时 wait 操作(simultaneous wait)。

Swait 操作定义如下:

Swait(S1, S2, ... , Sn) {while(true) {if(S1 >= 1 && S2 >= 1 && ... && Sn >= 1) {for(i = 1; i <= n; ++i) Si = Si - 1;break;  //分配完资源后,直接退出while循环} else {/*place the process in the waiting queue associated withthe first Si found with Si<1, and set the program countof this process to the beginning of Swait operation*/}}
}

Ssignal 操作定义如下:

Ssignal(S1, S2, ... , Sn) {for(i = 1; i <= n; ++i) Si = Si + 1;/*remove all the process waiting in the queueassociated with Si into the ready queue*/
}

4. 信号量集

在每次分配时,采用信号量集来控制,可以分配多个资源。

Swait 操作定义如下:

Swait(S1, t1, d1, ... , Sn, tn, dn) {while(true) {if(S1 >= t1 && ... && Sn >= t1) {for(i = 1; i <= n; ++i) Si = Si - di;break;  //分配完资源后,直接退出while循环} else {/*place the process in the waiting queue associated withthe first Si found with Si

Ssignal 操作定义如下:

Ssignal(S1, d1, ... , Sn, dn) {for(i = 1; i <= n; ++i) Si = Si + di;/*remove all the process waiting in the queueassociated with Si into the ready queue*/
}

三种特例

1)Swait(S, d, d):只有一种信号量 S,允许进程每次申请 d 个资源,当现有资源少于 d 时,不予分配。

2)Swait(S, 1, 1):只有一种信号量 S,允许进程每次申请 1 个资源,当现有资源少于 1 时,不予分配。当 S = 1 时,代表资源总量为 1,从而信号量集退化为互斥信号量;当 S > 1 时,代表资源总量大于 1,从而信号量集退化为记录型信号量。

3)Swait(S, 1, 0):可控开关。当 S >= 1 时,允许多个进程进入某特定区;当 S = 0 时,将阻止任何进程进入特定区。

读写文件举例:允许多个读进程进入临界区,但一旦有一个写进程进入临界区,则将阻止任何进程进入临界区。

P0:Swait(S, 1, 0)  //S>=1成立,且不改变信号量
P1:Swait(S, 1, 0)  //S>=1成立,且不改变信号量
Pw:Swait(S, 1, 1)  //S>=1成立,且S-1=0
P2:Swait(S, 1, 0)  //S>=1不成立

2.4.4 信号量的应用

1. 利用信号量实现进程互斥

为使多个进程能互斥地访问某临界资源,只须为该资源设置一互斥信号量 mutex,并设其初始值为 1,然后将各进程访问该资源的临界区 CS 置于 wait(mutex) 和 signal(mutex) 操作之间即可。

  1. 设置一互斥信号量 mutex
  2. 设其初始值为 1
  3. 将临界区 CS 置于 wait(mutex) 和 signal(mutex) 之间

利用信号量实现两个进程互斥的描述如下:

  • mutex 互斥
  • semaphore 信号量
  • 老师用 Pascal 写的,我不能保证我语法正确
var mutex:semaphore:=1; //将mutex定义为semaphore类型,且赋初值为1
begin
parbeginprocess1: beginrepeatwait(mutex);//critical sectionsignal(mutex);//remainder sectionuntil falseendprocess2: beginrepeatwait(mutex);//critical sectionsignal(mutex);//remainder sectionuntil falseendparend
end

注意:

  • 对于互斥型信号量,wait(mutex) 和 signal(mutex) 必须成对出现;
  • 缺少 wait(mutex) 导致系统混乱,不能保证对临界资源的互斥访问;
  • 缺少 signal(mutex) 会使临界资源永远不被释放,等待该资源的进程不能被唤醒。

2. 利用信号量实现前趋关系

利用信号量来描述程序或语句之间的前趋关系。

其中,Si 是需要执行的语句。

p1(){ S1; signal(a); signal(b); }
p2(){ wait(a); S2; signal(c); signal(d); }
p3(){ wait(b); S3; signal(e); }
p4(){ wait(c); S4; signal(f); }
p5(){ wait(d); S5; signal(g); }
p6(){ wait(e); wait(f); wait(g); S6; }void main() {semaphore a, b, c, d, e, f, g;//将信号量初值均设置为0,若后续进程试图执行则必被阻塞a.value = b.value = c.value = 0;d.value = e.value = f.value = g.value = 0;cobegin  //采用并行执行p1(); p2(); p3(); p4(); p5(); p6();coend;
}

2.4.5 管程机制

当共享资源用共享数据结构表示时,资源管理程序可用对该数据结构进行操作的一组过程来表示(例如,资源的请求过程 request 和释放过程 release),我们把这样一组相关的数据结构和过程一并称为管程(monitors)。
Hansan 为管程所下的定义是:“一个管程定义了一个数据结构和能为并发进程所执行(在该数据结构上)的一组操作,这组操作能同步进程和改变管程中的数据”。

1. 管程的组成

  • 管程的名字
  • 局部于管程的共享变量说明
  • 对该数据结构进行操作的一组过程
  • 对局部于管程的数据设置初始值的语句

Monitor(管程)—— 面向对象方法  

2. 管程的主要特点

局部数据变量只能被管程的过程访问,任何外部过程都不能访问。

一个进程通过调用管程的一个过程进入管程。

在任何时候,只能有一个进程在管程中执行,调用管程的任何其他进程都被挂起,以等待管程变成可用的。

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...