2022 Python寒假级高培训 第四次 笔记

一、信号量:某一段代码同一时间只能被n个进程执行
例子:
#信号量:控制并发数
import threading
import time
def run(n):
    semaphore.acquire() #启动事件量
    print(n)
    time.sleep(1)
    semaphore.release()#释放事件量

if __name__ == '__main__':
    semaphore = threading.Semaphore(5)#一次运行五个线程,其中一个线程结束锁释放
    for i in range(50):
        t = threading.Thread(target=run,args=(i,))
        t.start()

二、Condition(条件变量)通常与一个锁关联。需要在多个Contidion中共享一个锁时,可以传递一个Lock/RLock实例给构造方法,否则它将自己生成一个RLock实例。

可以认为,除了Lock带有的锁定池外,Condition还包含一个等待池,池中的线程处于状态图中的等待阻塞状态,直到另一个线程调用notify()/notifyAll()通知;得到通知后线程进入锁定池等待锁定。

Condition():

  • acquire(): 线程锁
  • release(): 释放锁
  • wait(timeout): 线程挂起,直到收到一个notify通知或者超时(可选的,浮点数,单位是秒s)才会被唤醒继续运行。wait()必须在已获得Lock前提下才能调用,否则会触发RuntimeError。
  • notify(n=1): 通知其他线程,那些挂起的线程接到这个通知之后会开始运行,默认是通知一个正等待该condition的线程,最多则唤醒n个等待的线程。notify()必须在已获得Lock前提下才能调用,否则会触发RuntimeError。notify()不会主动释放Lock。
  • notifyAll(): 如果wait状态线程比较多,notifyAll的作用就是通知所有线程
'''条件变量'''
import threading
import time

def run(x):
    con.acquire()
    print(f'线程{x}')
    con.notify() #告诉下边一个线程wait结束
    print(f'线程{x}挂起')
    con.wait()
    time.sleep
    print(f'线程{x}再次启动')
    con.notify()
    con.release()

if __name__ == '__main__':
    con = threading.Lock()  #实例化条件变量
    # for i in range(10):
    t = threading.Thread(target=run,args=(1,))
    t.start()
例子:实现场景:当a同学王火锅里面添加鱼丸加满后(最多5个,加满后通知b去吃掉),通知b同学去吃掉鱼丸(吃到0的时候通知a同学继续添加)
# coding=utf-8
import threading
import time

con = threading.Condition()

num = 0

# 生产者
class Producer(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        # 锁定线程
        global num
        con.acquire()
        while True:
            print "开始添加!!!"
            num += 1
            print "火锅里面鱼丸个数:%s" % str(num)
            time.sleep(1)
            if num >= 5:
                print "火锅里面里面鱼丸数量已经到达5个,无法添加了!"
                # 唤醒等待的线程
                con.notify()  # 唤醒小伙伴开吃啦
                # 等待通知
                con.wait()
        # 释放锁
        con.release()

# 消费者
class Consumers(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        con.acquire()
        global num
        while True:
            print "开始吃啦!!!"
            num -= 1
            print "火锅里面剩余鱼丸数量:%s" %str(num)
            time.sleep(2)
            if num <= 0:
                print "锅底没货了,赶紧加鱼丸吧!"
                con.notify()  # 唤醒其它线程
                # 等待通知
                con.wait()
        con.release()

p = Producer()
c = Consumers()
p.start()
c.start()

三、事件
(1)一个信号可以使所有的进程进入阻塞状态
(2)也可以控制所有的进程解除阻塞
(3)一个事件被创建之后,默认是阻塞状态

例子:

import threading
import time

def car():
    while True:
        if event.is_set():  #如果事件在执行
            print('小车行驶')
        else:
            print('小车停止')
            event.wait()    #等待事件

def set_event():
    while True:
        event.set() #启动事件
        time.sleep(1)
        event.clear()   #清除事件
        time.sleep(1)

if __name__ == '__main__':
    event = threading.Event() #创建事件
    car1 = threading.Thread(target=car)
    car1.start()
    set_e = threading.Thread(target=set_event)
    set_e.start()

视频讲解:https://space.bilibili.com/196858266/channel/collectiondetail?sid=57996

Condition()条件变量:

官方文档:threading --- 基于线程的并行 — Python 3.9.9 文档

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值