Python 线程条件变量 Condition - Python零基础入门教程

目录

零基础 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

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容