进程同步和信号量 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操作等待,可能会出现忙等情况
即不满足让权等待
经验分享 程序员 微信小程序 职场和发展