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

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

  • 相关阅读:
    NOI-OJ 2.2 ID:6261 汉诺塔
    NOI-OJ 2.2 ID:1696 逆波兰表达式
    NOI-OJ 2.2 ID:8758 2的幂次方表示
    NOI-OJ 2.2 ID:3089 爬楼梯
    NOI-OJ 1.13 ID:34 确定进制
    NOI-OJ 1.7 ID:21 单词替换
    NOI-OJ 1.13 ID:23 区间内的真素数
    【模板】欧拉筛法
    [SHOI2002]滑雪
    【Luogu1217】[USACO1.5]数字三角形(数塔问题) ——动态规划基础
  • 原文地址:https://www.cnblogs.com/shuopython/p/14926943.html
Copyright © 2011-2022 走看看