P.V操作原语和信号量(搜狐面试题)

来源:互联网 发布:淘宝开店怎么推广宣传 编辑:程序博客网 时间:2024/05/21 14:47

PV操作原语和信号量sem是计算机操作系统进程和线程同步的核心手段,虽然说起来只有句话,但有几个点非常容易引起模糊。先把PV操作的说明如下:

P操作原语:

1. sem 减1

2. 若sem 大于等于0,线程继续执行.

3. 若sem < 0 ,线程进入阻塞队列.

V 操作原语:

1. sem加1

2. 若sem 大于 0, 线程继续执行

3. 若sem 小于等于0,唤醒阻塞队例的线程

问题1.原语概念 
教科书上一般定义是不允许发生中断,一段必须连续执行的指令。在Dijkstra发明原语概念的时代,CPU应该都是单核的,多线程是单个CPU分时间片执行,所有只要是保证是” 连续执行”,就不会发生执行一个线程P操作的sem减1后,另一个线程V操作sem 加1。这意味着可以在现有的程序层面就可以实现多线程的同步而不需要别的指令或硬件。但在现在的多核时代,完全有可能在一个核上执行P操作sem减1后,另一个核上执行V操作sem加1,修改相同的地址空间,从而破坏sem的状态. 这方面.NET和Java都提供了volatile关键字,估计是添加的新的指令来保证,不过还好,这是操作系统操心的事情,操作系统保证原语概念的完整性。

问题2. 信号量

信号量sem在PV操作里具有三元性质.

让我们来看一个具体的实例: 假设现在的执行场景是有三个线程A,B,C进入一个信号量为1的临界资源,

1. 当线程A进入时,执行P操作, sem=0,线程A继续执行.

2. 当线程B进入时,线程A假设仍在占用临界资源, B执行P操作,sem = -1,B进入等待队列。

3. 当线程C进入时,线程A假设仍在占用临界资源, C执行P操作,sem = -2,C进入等待队列

 

通过以上的步骤可以发现:

1) 当sem > 0 时,表示可用的临界资源的数量

2) 当sem = 0时,表示无可用的资源,也没有阻塞的线程

3) 当sem <0 时,sem的绝对值表示阻塞队列的线程数

 

问题3.对V操作2,3步骤的解释

V操作的第2步,sem > 0 ,线程继续执行.有些人这个地方不解,sem > 0不是代表有资源可用吗?为什么不是唤醒其它的线程。其实正是sem >0 ,sem当前的意义是有资源可用,而没有阻塞的线程,所有根本不需要唤醒.

V操作的第3步,sem 小于等于0, 唤醒阻塞队例的线程. sem < 0很多人直觉认识都是没资源可用了,干吗还唤醒阻塞队列的线程(包括我)。通过问题2的分析,在这个时候sem代表的是阻塞队列的线程数 ,所以需要唤醒. 让我们接着问题2的步骤.

4) 线程A资源使用完,执行V操作,sem = -1, 唤醒阻塞队列的线程(假设FIFO),B线程进入临界资源开始执行,注意,B不会再执行P操作,因为进入阻塞队列前已执行.P,V操作必须成对执行。

5) B使用完资源后,执行V操作,sem = 0; 唤醒阻塞队列的线程,C线程进入临界资源开始执行,C也不会再执行P操作

6) C使用完资源,执行V操作, sem = 1

 

 

PV操作由P操作原语和V操作原语组成(原语是不可中断的过程)。对信号量进行操作,具体定义如下:

P(S):
①将信号量S的值减1,即S = S - 1;
②如果s >= 0,则该进程继续执行;否则该进程置为等待状态,排入等待队列。
V(S):
①将信号量S的值加1,即S = S + 1;
②如果S > 0,则该进程继续执行;否则释放队列中第一个等待信号量的进程。
PV操作的意义:我们用信号量及PV操作来实现进程的同步和互斥。PV操作属于进程的低级通信。
信号量(semaphore)的数据结构为一个值和一个指针,指针指向等待该信号量的下一个进程。信号量的值与相应资源的使用情况有关。当它的值大于0时,表示当前可用资源的数量;当它的值小于0时,其绝对值表示等待使用该资源的进程个数。注意,信号量的值仅能由PV操作来改变。
一般来说,信号量S >= 0时,S表示可用资源的数量。执行一次P操作意味着请求分配一个单位资源,因此S的值减1;当S<0时,表示已经没有可用资源,请求者必须等待别的进程释放该类资源,它才能运行下去。而执行一个V操作意味着释放一个单位资源,因此S的值加1;若S <= 0,表示有某些进程正在等待该资源,因此要唤醒一个等待状态的进程,使之运行下去。也就是说,有一个未被占用的资源就可以让一个阻塞的进程执行,
而不是S为正是才可以执行。

0 0
原创粉丝点击