zoukankan      html  css  js  c++  java
  • Python 线程条件变量 Condition

    目录

    零基础 Python 学习路线推荐 : Python 学习目录 >> Python 基础入门

    对于线程与线程之间的交互我们在前面的文章已经介绍了 Python 互斥锁 Lock / Python 事件 Event , 今天继续介绍一种线程交互方式 – 线程条件变量 Condition

    一.Python 线程条件变量 Condition 函数

    • acquire — 线程锁,注意线程条件变量 Condition 中的所有相关函数使用必须在acquire / release 内部操作;
    • release — 释放锁,注意线程条件变量 Condition 中的所有相关函数使用必须在acquire / release 内部操作;
    • **wait( timeout ) **— 线程挂起(阻塞状态),直到收到一个 notify 通知或者超时才会被唤醒继续运行(超时参数默认不设置,可选填,类型是浮点数,单位是秒)。wait 必须在已获得 Lock 前提下才能调用,否则会触发 RuntimeError;
    • **notify(n=1) **— 通知其他线程,那些挂起的线程接到这个通知之后会开始运行,缺省参数,默认是通知一个正等待通知的线程,最多则唤醒 n 个等待的线程。 notify 必须在已获得 Lock 前提下才能调用,否则会触发 RuntimeError ,notify 不会主动释放 Lock ;
    • notifyAll — 如果 wait 状态线程比较多,notifyAll 的作用就是通知所有线程;

    二.Python 线程条件变量 Condition 原理

    Python 互斥锁 Lock,主要作用是并行访问共享资源时,保护共享资源,防止出现脏数据。

    Python 条件变量 Condition 也需要关联互斥锁,同时 Condition 自身提供了 wait / notify / notifyAll 方法,用于阻塞 / 通知其他并行线程,可以访问共享资源了。

    可以这么理解,Condition 提供了一种多线程通信机制,假如线程 1 需要数据,那么线程 1 就阻塞等待,这时线程 2 就去制造数据,线程 2 制造好数据后,通知线程 1 可以去取数据了,然后线程 1 去获取数据。

    三.Python 线程条件变量 Condition 使用

    案例一:成语接龙

    # !usr/bin/env python
    # -*- coding:utf-8 _*-
    """
    @Author:猿说编程
    @Blog(个人博客地址): www.codersrc.com
    @File:Python 线程条件变量 Condition.py
    @Time:2021/05/04 07:37
    @Motto:不积跬步无以至千里,不积小流无以成江海,程序人生的精彩需要坚持不懈地积累!
    
    """
    
    # 导入线程模块
    import threading
    
    # 创建条件变量condition
    con = threading.Condition()
    
    def thread_one(name):
        # 条件变量condition 线程上锁
        con.acquire()
    
        print("{}:成语接龙准备好了吗".format(name))
        # 唤醒正在等待(wait)的线程
        con.notify()
    
        # 等待对方回应消息,使用wait阻塞线程,等待对方通过notify唤醒本线程
        con.wait()
        print("{}:一干二净".format(name))
        # 唤醒对方
        con.notify()
    
        # 等待消息答应
        con.wait()
        print("{}:一天就知道看抖音美女,给你来个简单点的,来了:毛手毛脚".format(name))
        # 唤醒对方
        con.notify()
    
        # 等待消息答应
        con.wait()
        print("{}:哟哟哟,不错不错!".format(name))
        # 唤醒对方
        con.notify()
    
        # 条件变量condition 线程释放锁
        con.release()
    
    def thread_two(name):
        # 条件变量condition 线程上锁
        con.acquire()
    
        # wait阻塞状态,等待其他线程通过notify唤醒本线程
        con.wait()
        print("{}:准备好了~开始吧!".format(name))
        # 唤醒对方
        con.notify()
    
        # 等待消息答应
        con.wait()
        print("{}:净你妹啊,没法接...来个简单点的...".format(name))
        # 唤醒对方
        con.notify()
    
        # 等待消息答应
        con.wait()
        print("{}:嘿,这个我知道:脚踏实地".format(name))
        # 唤醒对方
        con.notify()
    
        con.release()
    
    if __name__ == "__main__":
    
        # 创建并初始化线程
        t1 = threading.Thread(target=thread_one,args=("A"))
        t2 = threading.Thread(target=thread_two,args=("B"))
    
        # 启动线程 -- 注意线程启动顺序,启动顺序很重要
        t2.start()
        t1.start()
    
        # 阻塞主线程,等待子线程结束
        t1.join()
        t2.join()
    
    
        print("程序结束!")
    
    
    '''
    输出结果:
    
    A:成语接龙准备好了吗
    B:准备好了~开始吧!
    A:一干二净
    B:净你妹啊,没法接...来个简单点的...
    A:一天就知道看抖音美女,给你来个简单点的,来了:毛手毛脚
    B:嘿,这个我知道:脚踏实地
    A:哟哟哟,不错不错!
    程序结束!
    '''
    

    案例二:生产者与消费者模式,以吃火锅为例:一盘老肉片有 10 块肉,吃完了又重新往锅里加….

    • 生产者:往锅里加老肉片,每次加一盘(10 块);
    • 消费者:吃煮熟的肉片,没吃一片,肉片数量减一,吃完为止;
    # !usr/bin/env python
      # -\_- coding:utf-8 \_\_-
    
      """
      @Author:猿说编程
      @Blog(个人博客地址): www.codersrc.com
      @File:Python 线程条件变量 Condition.py
      @Time:2021/05/04 07:37
      @Motto:不积跬步无以至千里,不积小流无以成江海,程序人生的精彩需要坚持不懈地积累!
    
      """
    
      # 导入线程模块
    
      import threading
      import time
    
      # 创建条件变量 condition
    
      con = threading.Condition()
      meat_num = 0
    
      def thread_consumers(): # 条件变量 condition 线程上锁
      con.acquire()
    
      # 全局变量声明关键字 global
    
            global meat_num
            meat_num = 0
    
      # 等待肉片下锅煮熟
    
            con.wait()
            while True:
                print("我来一块肉片...")
                meat_num -= 1
                print("剩余肉片数量:%d"%meat_num)
                time.sleep(0.5)
                if meat_num == 0:
                    #  肉片吃光了,通知老板添加肉片
                    print("老板,再来一份老肉片...")
                    con.notify()
                    #  肉片吃光了,等待肉片
                    con.wait()
    
      # 条件变量 condition 线程释放锁
    
            con.release()
    
      def thread_producer(): # 条件变量 condition 线程上锁
      con.acquire() # 全局变量声明关键字 global
      global meat_num
    
      # 肉片熟了,可以开始吃了
    
            meat_num = 10
            print("肉片熟了,可以开始吃了...")
            con.notify()
            while True:
                #  阻塞函数,等待肉片吃完的通知
                con.wait()
                meat_num = 10
                #  添加肉片完成,可以继续开吃
                print("添加肉片成功!当前肉片数量:%d"%meat_num)
                time.sleep(1)
                con.notify()
    
      con.release()
    
      if **name** == "**main**": # 创建并初始化线程
      t1 = threading.Thread(target=thread_producer)
      t2 = threading.Thread(target=thread_consumers)
    
      # 启动线程 -- 注意线程启动顺序,启动顺序很重要
    
            t2.start()
            t1.start()
    
      # 阻塞主线程,等待子线程结束
    
            t1.join()
            t2.join()
    
      print("程序结束!")
    
      '''
      输出结果:
    
      肉片熟了,可以开始吃了...
      我来一块肉片...
      剩余肉片数量:9
      我来一块肉片...
      剩余肉片数量:8
      我来一块肉片...
      剩余肉片数量:7
      我来一块肉片...
      剩余肉片数量:6
      我来一块肉片...
      剩余肉片数量:5
      我来一块肉片...
      剩余肉片数量:4
      我来一块肉片...
      剩余肉片数量:3
      我来一块肉片...
      剩余肉片数量:2
      我来一块肉片...
      剩余肉片数量:1
      我来一块肉片...
      剩余肉片数量:0
      老板,再来一份老肉片...
      添加肉片成功!当前肉片数量:10
      我来一块肉片...
      剩余肉片数量:9
      我来一块肉片...
      剩余肉片数量:8
      我来一块肉片...
      剩余肉片数量:7
      .............
      '''
    

    注意:

    • 1.全局变量要声明关键字 global;
    • 2.注意线程的启动顺序,这个很重要;

    四.Python 线程条件变量 Condition 总结

    注意线程互斥锁 Lock / 线程事件 Event / 线程条件变量 Condition 三者的区别,场景不同,使用方式也不同,前两者一般可以作为简单的线程交互,线程条件变量 Condition 可以用于比较复杂的线程交互

    五.猜你喜欢

    1. Python 条件推导式
    2. Python 列表推导式
    3. Python 字典推导式
    4. Python 函数声明和调用
    5. Python 不定长参数 *argc/**kargcs
    6. Python 匿名函数 lambda
    7. Python return 逻辑判断表达式
    8. Python 字符串/列表/元组/字典之间的相互转换
    9. Python 局部变量和全局变量
    10. Python type 函数和 isinstance 函数区别
    11. Python is 和 == 区别
    12. Python 可变数据类型和不可变数据类型
    13. Python 浅拷贝和深拷贝
    14. Python 文件读写操作
    15. Python 异常处理
    16. Python 模块 import
    17. Python __name__ == ‘__main__’详细解释

    未经允许不得转载:猿说编程 » Python 线程条件变量 Condition

    本文由博客 - 猿说编程 猿说编程 发布!

  • 相关阅读:
    关于celery踩坑
    关于git的分批提交pull requests流程
    SymGAN—Exploiting Images for Video Recognition: Heterogeneous Feature Augmentation via Symmetric Adversarial Learning学习笔记
    AFN—Larger Norm More Transferable: An Adaptive Feature Norm Approach for Unsupervised Domain Adaptation学习笔记
    Learning to Transfer Examples for Partial Domain Adaptation学习笔记
    Partial Adversarial Domain Adaptation学习笔记
    Partial Transfer Learning with Selective Adversarial Networks学习笔记
    Importance Weighted Adversarial Nets for Partial Domain Adaptation学习笔记
    Exploiting Images for Video Recognition with Hierarchical Generative Adversarial Networks学习笔记
    improved open set domain adaptation with backpropagation 学习笔记
  • 原文地址:https://www.cnblogs.com/shuopython/p/14926943.html
Copyright © 2011-2022 走看看