博客
关于我
Python 中Semaphore 信号量对象、Event事件、Condition
阅读量:797 次
发布时间:2023-03-06

本文共 3621 字,大约阅读时间需要 12 分钟。

信号量机制在多线程环境中的应用

信号量(Semaphore)是一种高级的锁机制,它与传统的锁机制有显著的区别。信号量内部维护一个计数器,而不是像传统锁那样通过占用一块独占资源来实现同步。信号量机制允许在资源占用数量超过信号量时,阻塞等待其他线程释放资源。这使得多个线程可以同时访问相同的代码区,从而提高了资源利用率。

信号量的基本原理

信号量的核心机制包括两个主要操作:acquire()release()

  • acquire() 方法:当调用 acquire() 时,信号量的内部计数器会减1。若计数器值为0时,当前线程会被阻塞,直到其他线程调用 release() 方法将计数器恢复为正值。

  • release() 方法:当调用 release() 时,信号量的内部计数器会加1。如果有其他线程正在等待,可以立即被唤醒并继续执行。

  • 信号量的计数器不能小于0。每当线程完成任务后,都应及时释放信号量,确保其他线程能够继续使用资源。

    示例:信号量的实际应用

    以下是一个典型的信号量使用示例:

    import threadingimport timesemaphore = threading.Semaphore(3)  # 允许最多3个线程同时获取锁def func():    if semaphore.acquire():        print(threading.current_thread().name + '获取锁')        time.sleep(5)        semaphore.release()        print(threading.current_thread().name + '释放锁')for i in range(10):    t = threading.Thread(target=func)    t.start()

    运行结果会显示:

    • Thread-1 获取锁
    • Thread-2 获取锁
    • Thread-3 获取锁
    • Thread-3 释放锁
    • Thread-2 释放锁
    • Thread-4 获取锁
    • Thread-5 获取锁
    • Thread-1 释放锁
    • Thread-6 获取锁
    • Thread-6 释放锁
    • Thread-7 获取锁
    • Thread-4 释放锁
    • Thread-8 获取锁
    • Thread-5 释放锁
    • Thread-9 获取锁
    • Thread-8 释放锁
    • Thread-10 获取锁
    • Thread-7 释放锁
    • Thread-9 释放锁
    • Thread-10 释放锁

    Event事件对象

    Event对象提供了一种简单的事件通知机制。它包含一个标志位,初始状态为false。通过调用 set() 方法可以将标志位设置为trueclear() 方法将其重置为falseis_set() 方法用于检查标志位的状态。

    Event对象的关键方法是 wait(),它可以接受一个超时参数。调用 wait() 时,当前线程会被阻塞,直到事件标志位被设置为true,或者超时(如果提供了超时参数)。

    示例:Event的实际应用

    import threadingimport timeevent = threading.Event()def service():    print('开启服务')    event.wait()  # 不带参数时,会一直阻塞直到event被设置为true    print('服务开启成功')def start():    time.sleep(3)    print('开始执行业务')    time.sleep(3)    event.set()  # 将事件标志位设置为truedef conn():    while True:        if not event.is_set():            print('数据库连接成功')            time.sleep(1)            event.set()            event.wait()            breakif __name__ == "__main__":    t1 = threading.Thread(target=conn)    t2 = threading.Thread(target=start)    t3 = threading.Thread(target=service)    t1.start()    t2.start()    t3.start()

    运行结果:

    • 开启服务
    • 数据库连接成功
    • 服务开启成功
    • 开始执行业务

    Condition条件对象

    Condition对象是一种更高级的锁,它允许开发者在复杂的多线程环境中实现更细粒度的控制。Condition对象内部维护一个默认的RLock锁,可以通过构造函数指定其他类型的锁。

    Condition对象提供了 acquire()release() 方法,与普通锁机制相同,但更高级的功能在于它还支持 wait()notify()notify_all() 方法。

  • wait() 方法:释放内部锁,并挂起当前线程,直到接收到通知或超时。

  • notify() 方法:唤醒一个被挂起的线程,但不会释放当前锁。

  • notify_all() 方法:唤醒所有被挂起的线程,同样不会释放当前锁。

  • 示例:Condition的实际应用

    以下是一个经典的生产者-消费者模式示例:

    from threading import Thread, Conditionimport timeimport randomqueue = []MAX_NUM = 10condition = Condition()class ProducerThread(Thread):    def run(self):        nums = range(5)        global queue        while True:            condition.acquire()            if len(queue) == MAX_NUM:                print("Queue full, producer is waiting")                condition.wait()                print("Space in queue, Consumer notified the producer")            num = random.choice(nums)            queue.append(num)            print("Produced", num)            condition.notify()            condition.release()            time.sleep(random.random())class ConsumerThread(Thread):    def run(self):        global queue        while True:            condition.acquire()            if not queue:                print("Nothing in queue, consumer is waiting")                condition.wait()                print("Producer added something to queue and notified the consumer")            num = queue.pop(0)            print("Consumed", num)            condition.notify()            condition.release()            time.sleep(random.random())producer = ProducerThread()consumer = ConsumerThread()producer.start()consumer.start()

    运行结果:

    • ProducerThread: Produced 2
    • ConsumerThread: Consumed 2
    • ProducerThread: Produced 3
    • ConsumerThread: Consumed 3
    • ...(结果会根据随机数生成,展示部分输出示例)

    转载地址:http://hyofk.baihongyu.com/

    你可能感兴趣的文章
    Python 判断字符串是否包含子字符串
    查看>>
    python 判断当前时间是否为零点
    查看>>
    python 利用pandas读取本地中CSV文件的指定列 列名重命名 并保存回本地
    查看>>
    python 利用pyspark读取HDFS中CSV文件的指定列 列名重命名 并保存回HDFS
    查看>>
    python 利用pyttsx3文字转语音
    查看>>
    python 利用已有Ner模型进行数据清洗合并
    查看>>
    python 到大数据开发工程师_如何成为一个大数据开发工程师?
    查看>>
    python 加密解密(base64, AES)
    查看>>
    Python 包管理器和 Node.js
    查看>>
    Python 单词字母顺序不变且所有倒排
    查看>>
    python 反射机制
    查看>>
    python 启动提示IDLE's subprocess didn't make conne...
    查看>>
    python 命令接口_实现“[命令][操作][参数]”样式的命令行接口?
    查看>>
    Python 和 OpenCV.如何检测图像中的所有(填充)圆形/圆形对象?
    查看>>
    Python 和 RabbitMQ - 聆听来自多个渠道的消费事件的最佳方式?
    查看>>
    python编辑器打不开_关于命令ride.py打不开RF,而是打开pycharm编辑器问题解决思路...
    查看>>
    python编译exe同时支持32位_第三周:同时管理64位和32位版本的Python,并用Pyinstaller打包成exe...
    查看>>
    Python 和Java 哪个更适合做自动化测试?
    查看>>
    Python编程:掌握高级语言程序设计。从零基础到精通,收藏这篇就够了!
    查看>>
    python 图片转ico
    查看>>