1.整型信号量是一个整数变量,除初始化外,对其只能执行两个操作,即wait(s)和signal(s),也叫p(s)和v(s)操作,均是原语操作,用来实现进程的同步,互斥.
2.记录型信号量
type semaphore
=
record
value:integer
L: list of process;
end
procedure wait(s)
var s: semaphore;
begin
s.value
=
s.value
-
1
;
if
(s.value
<
0
) then block(s.L)
end
procedure signal(s)
var s: semaphore
begin
s.value
=
s.value
+
1
;
if
(s.value
<=
0
) then wakeup(s.L)
end
结论:
(1) 若信号量s为正值,则等于在封锁进程之前对信号梁可以施行的p操作数,也就是s所代表的实际可以使用的物理资源数.
(2) 若信号量s为负值,则其绝对值等于排列在该信号量s队列之中等待的进程个数,也就等于对信号量s实施p操作而被封锁起来并进入信号量s队列的进程数.
(3)p操作一般代表请求一个资源,v操作一般代表着释放一个资源,在一定条件下,p操作代表挂起进程操作,v操作代表唤醒被挂起的进程.
3.经典同步问题
1)生产者/消费者问题
a) 问题一:有一个生产者和一个消费者,共享一个缓冲区.两者要互斥访问缓冲区.
解:定义两个信号量:empty表示缓冲是否为空,初值为1,即初始时可以存入一件物品.full表示缓冲区中是否有物品,初值为0,即初始时缓冲区没有物品.
程序:
begin
buffer:integer
empty,full:semaphore
=
1
,
0
;
cobegin
process Producer
begin
L1:生产一件物品
wait(empty);
buffer
=
product;
signal(full);
goto
L1;
end
process Consumer
begin
L2:wait(full);
从缓冲区取出一件物品;
signal(empty);
消费掉物品
goto
L2;
end
coend
end
注:
(1)进程互斥只需要一个信号量,而同步可能要两个信号量.
(2)p,v操作仍然要成对,但在进程进入临界区前后调用的是针对不同信号量的wait,signal操作,而进程互斥时是针对相同的信号量.
(3)至少有一个信号量的初值>=1,否则所有进程无法执行,一般是指管理是否允许访问共享资源的那个信号量.如这里的empty设为1,如果缓冲区容量为n,则可以设为n;
b)问题二:m个生产者,n个消费者,容量为r的缓冲区,(m,n,r都大于1),不要生产者和消费者互斥存取物品.
解:1)生产者和消费者之间要同步,类似问题一,用两个信号量empty,full;2)m个生产者之间要互斥,n个消费者之间也要互斥,但生产者和消费者不用互斥存取物品,因此设两个计数器in,out和相应的互斥信号量mutex1,mutex2
程序:
begin
buffer:array[
0
r
-
1
]: integer
in
,
out
:integer
=
0
,
0
;
empty
=
r,full
=
0
,mutex1
=
1
,mutex2
=
1
:semaphore;
cobegin
process Producer
-
i(i
=
1
,
2
m)
begin
L1:生产一件物品;
wait(empty)

这篇博客主要介绍了操作系统中信号量的概念,包括整型信号量和记录型信号量,并通过生产者/消费者问题、读者/写者问题以及哲学家进餐问题阐述了同步和互斥的解决方案。强调了P、V操作的使用以及避免死锁的关键策略。


被折叠的 条评论
为什么被折叠?



