进程同步和信号量 PV操作
进程同步和PV操作理解
首先用python模拟了生产者消费者问题,代码如下:
import threading
import random
BUFFER_SIZE = 10
buffer = [[]] * 10
counter = 0
in_ = 0
out_ = 0
item = 0
def productor():
global in_, buffer, counter, item
while 1:
# 发信号停
while counter == BUFFER_SIZE:
print("productor wait...
")
item = random.randint(1, 1000)
buffer[in_].append(item)
print("product {}
".format(item))
print("product counter {}
".format(counter))
in_ = (in_+1) % BUFFER_SIZE
# 发信号走
counter += 1
def customer():
global out_, buffer, counter, item
while 1:
# 发信号停
while counter == 0:
print("customer wait...
")
item = buffer[out_].pop()
print("custom {}
".format(item))
print("custom counter {}
".format(counter))
out_ = (out_+1) % BUFFER_SIZE
# 发信号走
counter -= 1
productorThread = threading.Thread(target=productor)
customerThread = threading.Thread(target=customer)
productorThread.start()
customerThread.start()
# 信号只能表达有还是没有,而信号量可以表达更丰富的信息
这里面没有用信号量来,是用counter来表示资源,信号量机制我觉得和counter不同的是,
信号量在大于0时,表示资源,在小于0时表示等待的进程
这也就是为什么PV操作要这样写
下面是伪代码,信号量是一种数据结构
semaphore{
变量 s 表示资源数量
进程 q 表示等待的进程 由阻塞队列表示
}
P(semaphore s)
s-- 表示资源数 - 1,
if s < 0
那么进程等待
V(semaphore s)
s++ 表示资源数 + 1
if s <= 0
那么唤醒阻塞队列中的进程
为什么上面是小于0等待,下面是小于等于0唤醒呢?我觉得原因如下;
首先信号量s在大于0时表示资源,小于0时表示等待进程个数
举个例子,以打水为例,可以往一个盆里倒水,但是每次只能从水池接一桶水,然后倒水,不能同时从盆里打水,盆里最终多可以容纳10桶水。
那么这里,最多能倒10桶水就是资源,设empty表示空闲资源即初始值为10(表示当前可倒10桶水,但是现在还没有),full表示盆中已有几桶水初始值为0(其实一些初学者迷惑在这里,为什么要设empty和full两个变量)
所以作为生产者,需要先进行P操作,即P(empty),empty会-1,并判断empty不小于0,那么继续,并且在结尾,需要V(full)操作,打了一桶水,那么盆中多一桶水。
假设empty此时是0,意思也就是说不能在倒水了,那么经过s--,此时empty变成-1,生产进程阻塞了,也就是说多了一个阻塞进程
对于喝水的也就是消费者来说,开始需要判断有没有水,也就是P操作,P(full),此时full为10,那么继续,一样的,结尾需要,V操作,因为喝水的用了一桶水,那么就是说
还可以再打一桶水,所以结尾需要V(empty),将可用资源+1,此时,empty变为0,并且进行V操作,即V(empty)因为V操作中,是小于等于0,所以从阻塞队列中唤醒生产者进程
由于生产者进程之前在P操作时阻塞,所以开始继续执行后面的语句,注意的是,这里是继续,继续,继续执行。
所以PV操作是走走停停的,上述的信号量机制是记录型信号量,不会出现满等情况,也就是满足让权等待
除了记录型信号量,还有整数型信号量,如下:
P():
while s <= 0;
s -= 1
v():
s += 1
在整数型信号量中,s 代表资源,记录型中还代表阻塞的进程数,
比如s小于等于0时,此时执行P操作等待,可能会出现忙等情况
即不满足让权等待
