原文链接:https://blog.csdn.net/qq_40760732/article/details/89513663
仅为学习记录
PV操作的特点:
原子性,P和V操作不可分!
连续性,P和V操作是不间断的。
P自己,V对方:P的是自己的信号量减1,V的是对方的信号量加1.
文章开头,先来一段要背的内容
接下来,先给两个网上的案例热热身
案例一:
import threading,time
lock_1 = threading.Semaphore(1) #检查售票员是否关门
lock_2 = threading.Semaphore(0) #检查司机是否停车
def 司机():
for i in range(3):
lock_1.acquire()
print('司机开车')
time.sleep(1)
print('驾驶')
print('到站停车')
lock_2.release()
def 售票员():
for i in range(3):
lock_2.acquire()
time.sleep(1)
print('打开车门')
print('乘客上下车')
time.sleep(1)
print('关上车门')
lock_1.release()
if __name__=='__main__':
p1 = threading.Thread(target=司机)
p2 = threading.Thread(target=售票员)
p1.start()
p2.start()
p1.join()
p2.join()
解释:
1.里面的lock_1,lock_2为两个信号量;
2.lock_1.acquire()为P操作,lock_1.release()为V操作;
3.lock_1 = threading.Semaphore(1)的意思是将信号量lock_1的初值赋为1。
注意:
Semaphore管理一个内置的计数器,
每当调用acquire()时内置计数器-1;
调用release() 时内置计数器+1;
计数器不能小于0;当计数器为0时,acquire()将阻塞线程直到其他线程调用release()。
我们将lock_1的初值赋为1,lock_2的初值赋为0,则先执行司机这一线程。
案例二:
import queue,random,threading
from time import sleep
s_1 = threading.Semaphore(1) # 临界区互斥信号量
s_2 = threading.Semaphore(5) # 判断是否有空闲缓冲区的信号量
s_3 = threading.Semaphore(0) # 判断缓冲区里是否有产品的信号量
def productor(i, q):
while True:
num = random.choice(['华为P30', '小米9', 'ViVo x27', 'iphone XR'])
print('生产者%d生产了产品%s' % (i, num))
s_2.acquire() # 是否有空缓冲区
s_1.acquire() # 缓冲区是否被占用
q.put(num)
sleep(1)
print('生产者%d把产品%s放入了仓库中' % (i, num))
s_1.release()
s_3.release()
def consumer(i, q):
while True:
s_3.acquire()
s_1.acquire()
num = q.get()
sleep(1)
print('消费者%d购买了产品%s' % (i, num))
s_1.release()
s_2.release()
if __name__ == '__main__':
q = queue.Queue(5) # 创建上限为5的缓冲区
# 创建4个生产者
for i in range(4):
threading.Thread(target=productor, args=(i, q)).start()
# 创建6个消费者
for i in range(6):
threading.Thread(target=consumer, args=(i, q)).start()
信号量:
设置三个信号量,一个信号量判断缓冲区是否被占用,一个信号量判断缓冲区是否有空,最后一个信号量判断缓冲区里是否有东西。
生产者:四个
消费者:六个
缓冲区:五个
某一时刻只能有一个线程或进程访问缓冲区,缓冲区没满时生产者可以往里面放东西,缓冲区没空时消费者可以从里面取东西。
PV操作的简单了解:
进程通常分为就绪、运行和阻塞三个工作状态。三种状态在某些条件下可以转换,三者之间的转换关系如下:
进程三个状态之间的转换就是靠PV操作来控制的。PV操作主要就是P操作、V操作和信号量。其中信号量起到了至关重要的作用。
信号量
信号量是最早出现的用来解决进程同步与互斥问题的机制。
信号量(Saphore)由一个值和一个指针组成,指针指向等待该信号量的进程。信号量的值表示相应资源的使用情况。信号量S>=0时,S表示可用资源的数量。执行一次P操作意味着请求分配一个资源,因此S的值减1;当S<0时,表示已经没有可用资源,S的绝对值表示当前等待该资源的进程数。请求者必须等待其他进程释放该类资源,才能继续运行。而执行一个V操作意味着释放一个资源,因此S的值加1;若S<0,表示有某些进程正在等待该资源,因此要唤醒一个等待状态的进程,使之运行下去。
注意,信号量的值只能由PV操作来改变。
最后来一句顺口溜笔记:
P减V加信号量
互斥信号量是1
唤醒进程跳临界
负阻正有0用完