Python | threading04 - 使用信号量,实现线程间同步

一、前言


先说一下信号量与互斥量之间的关系。信号量的一个特殊的应用是互斥锁(互斥量),当信号量的最大数量是1时,它跟互斥锁(互斥量)的作用相同。

以下摘自《python并行编程》中文版:
在这里插入图片描述

二、生产者-消费者模型


本次的代码目的如下:

  1. 生成者producer每隔3秒时间同步一次消费者1(customer1)与消费者2(customer2)。
  2. 消费者1(customer1)与消费者2(customer2)每一次被同步都可以运行两次。
    在这里插入图片描述

2.1、代码

# python3.9
import time
import threading

se1 = threading.Semaphore(0)  # se1信号量的初始数量是0
se2 = threading.Semaphore(0)  # se2信号量的初始数量是0

# 消费者1线程函数
def customer1():
    global se1
    while True:
        # print("customer1请求se1信号量。")
        se1.acquire()  # 向se1信号量请求一个信号
        print("customer1请求信号量成功,time:%s" % time.perf_counter())

# 消费者2线程函数        
def customer2():
    global se2
    while True:
        # print("customer2请求se2信号量。")
        se2.acquire()  # 向se1信号量请求一个信号
        print("customer2请求信号量成功,time:%s" % time.perf_counter())

# 生产者线程函数
def producer():
    while True:
        time.sleep(3)  # 休眠3秒钟
    
        # 释放se1两个信号
        se1.release()
        se1.release()
    
        # 释放se2两个信号
        se2.release()
        se2.release()
        print("producer释放完信号量,其他线程将被同步。time:%s" % time.perf_counter())

# 主线程函数
def main():
    t1 = threading.Thread(target=producer,name="thread_producer",daemon=True)    # 创建producer子线程
    t2 = threading.Thread(target=customer1,name="thread_customer1",daemon=True)  # 创建cusotmer1子线程
    t3 = threading.Thread(target=customer2,name="thread_customer2",daemon=True)  # 创建customer2子线程
    t1.start()  # 启动producer线程 
    t2.start()  # 启动customer1线程
    t3.start()  # 启动customer2线程
    t1.join()   # 子线程producer是无限循环的线程,所以主线程需要等待它运行结束
    t2.join()   # 子线程customer1是无限循环的线程,所以主线程需要等待它运行结束
    t3.join()   # 子线程customer2是无限循环的线程,所以主线程需要等待它运行结束
    print("主线程运行结束!")
    
    
    
if __name__ == "__main__":
    main()

2.2、运行的结果

在这里插入图片描述
python多线程的信号量跟单片机RTOS的信号量真的很相似。如果之前接触过RTOS的信号量的话,python的信号量也很快可以掌握。

2.3、Semaphore没有设置上限值

在代码中,只设置了信号量的初始值。
在这里插入图片描述
因为我将信号量的初始值设为0,所以线程customer1与线程customer2在刚被创建的时候就进入了阻塞态(因为没有信号量)。
在这里插入图片描述
Semaphore没有设置上限值,所以可能会出现信号量释放的次数过多(多于本来规划的值)。为了避免这个情况的出现,Python的多线程还有另外一个工具叫做有界信号量。
单片机的RTOS上的信号量跟python的有界信号量一样,能防止信号量释放的次数过多。

猜你喜欢

转载自blog.csdn.net/wallace89/article/details/122527717