信号量、条件变量、事件

教程:

信号量(Semaphore)

  • 信号量是一把锁,用来控制线程并发数的。信号量是多把锁,同时允许多个线程来更改数据。
  • 使用语法:
    threading.Semaphore(value)用以创建信号量对象
    acquire()用以设置线程锁
    release()用以释放线程锁
  • 首先,我们需要使用 threading.Semaphore(value)创建一个信号量的实例,创建实例时,需要指定一个 value 参数 大小,表示内部维护的计数器的大小,默认为 1。接着,在我们对临界资源进行访问的时候,调用 acquire(),此时内置计数器 -1,直到为 0 的时候就阻塞。资源调用完毕后调用release(),内置计数器 +1,并让某个线程的 acquire() 从阻塞变为不阻塞。
  • 实例:
import threading
import time


def run(n):
    semaphore.acquire()  # 设置线程锁
    print(n)
    time.sleep(3)  # 令当前执行的线程暂停2秒后再继续执行
    semaphore.release()  # 释放线程锁


if __name__ == '__main__':
    semaphore = threading.Semaphore(5)  # 创建信号量对象,内部维护的计数器的大小设为5,即最多允许5个线程同时运行
    for i in range(50):
        t = threading.Thread(target=run, args=(i, ))  # 创建线程
        t.start()  # 启动线程活动

条件变量(Condition)

  • 条件变量总是与某种类型的锁对象相关联,锁对象可以通过传入获得,或者在缺省的情况下自动创建。当多个条件变量需要共享同一个锁时,传入一个锁很有用。锁是条件对象的一部分,你不必单独地跟踪它。

  • 使用语法
    threading.Condition()用以创建条件变量对象
    acquire()用以设置线程锁
    release()用以释放线程锁
    notify(n=1) 通知其他线程,那些挂起的线程接到这个通知之后会开始运行,默认是通知一个正等待该condition的线程,
    最多则唤醒n个等待的线程。notify()必须在已获得Lock前提下才能调用,否则会触发RuntimeError。notify()不会主动
    释放Lock。
    wait(timeout)将线程挂起,直到收到一个notify通知或者超时(可选的,浮点数,单位是秒s)才会被唤醒继续运行。
    wait()必须在已获得Lock前提下才能调用,否则会触发RuntimeError。

  • 实例:

import threading
import time


def run(x):
    con.acquire()  # 设置线程锁
    print(f"我是{x}线程")
    # notify(n=1): 通知其他线程,那些挂起的线程接到这个通知之后会开始运行,默认是通知一个正等待该condition的线程,最多则唤醒n个等待的线程。notify()必须在已获得Lock前提下才
    # 能调用,否则会触发RuntimeError。notify()不会主动释放Lock。
    con.notify()
    print(f"线程{x}挂起")
    # wait(timeout)将线程挂起,直到收到一个notify通知或者超时(可选的,浮点数,单位是秒s)才会被唤醒继续运行。wait()必须在已获得Lock前提下才能调用,否则会触发RuntimeError。
    con.wait()
    time.sleep(1)
    print(f"线程{x}再次启动")
    con.notify()
    con.release()  # 释放线程锁


if __name__ == '__main__':
    con = threading.Condition()  # 创建条件变量对象
    for i in range(10):
        t = threading.Thread(target=run, args=(i, ))  # 创建线程
        t.start()  # 启动线程活动

事件(Event)

  • 事件处理的机制:全局定义了一个内置标志Flag,如果Flag值为 False,那么当程序执行 event.wait方法时就会阻塞,如果Flag值为True,那么event.wait 方法时便不再阻塞。Event其实就是一个简化版的 Condition。Event没有锁,无法使线程进入同步阻塞状态。
  • 使用语法:
    threading.Event() 用以创建事件对象
    set()用以将内部标志设为True,并通知所有处于等待阻塞状态的线程恢复运行状态
    clear()用以将内部标志设为False
    is_set当且仅当内部标志为True时返回True
    wait(timeout)阻塞直到内部标志为真,如果内部标志为True将立即返回,否则阻塞线程至等待阻塞状态,等待其他线程调用set()或
    发生超时

实例:

"""
事件处理的机制:全局定义了一个内置标志Flag,如果Flag值为 False,那么当程序执
行 event.wait方法时就会阻塞,如果Flag值为True,那么event.wait 方法时便不再
阻塞。Event其实就是一个简化版的 Condition。Event没有锁,无法使线程进入同步阻
塞状态。
"""

import threading
import time


def car():
    while True:
        if event.is_set():  # is_set:当且仅当内部标志为True时返回True
            print("小车行驶")
        else:
            print("小车停止")
            event.wait()  # 阻塞直到内部标志为真,如果内部标志为True将立即返回,否则阻塞线程至等待阻塞状态,等待其他线程调用set()或发生超时


def set_event():
    while True:
        event.set()  # 将内部标志设为True,并通知所有处于等待阻塞状态的线程恢复运行状态
        time.sleep(1)
        event.clear()  # 将内部标志设为False
        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()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值