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

一.线程条件变量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的作用就是通知所有线程;

二.线程条件变量Condition原理

在前面的文章已经介绍过互斥锁,主要作用是并行访问共享资源时,保护共享资源,防止出现脏数据。python 条件变量Condition也需要关联互斥锁,同时Condition自身提供了wait/notify/notifyAll方法,用于阻塞/通知其他并行线程,可以访问共享资源了。可以这么理解,Condition提供了一种多线程通信机制,假如线程1需要数据,那么线程1就阻塞等待,这时线程2就去制造数据,线程2制造好数据后,通知线程1可以去取数据了,然后线程1去获取数据。

三.线程条件变量Condition使用

案例一:成语接龙

# !usr/bin/env python
# -*- coding:utf-8 _*-
"""
@Author:何以解忧
@Blog(个人博客地址): shuopython.com
@WeChat Official Account(微信公众号):猿说python
@Github:www.github.com @File:python_.py
@Time:2019/10/21 21:25 @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块);

消费者:吃煮熟的肉片,没吃一片,肉片数量减一,吃完为止;

# 导入线程模块
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.注意线程的启动顺序,这个很重要;

四.重点总结

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

猜你喜欢:

1.python线程创建和参数传递

2.python线程互斥锁Lock

3.python线程事件Event

4.python return逻辑判断表达式

转载请注明:猿说Python » python条件变量Condition

技术交流、商务合作请直接联系博主
扫码或搜索:猿说python
猿说python
微信公众号 扫一扫关注

python线程条件变量Condition(31)的更多相关文章

  1. python线程的条件变量Condition的用法实例

      Condition 对象就是条件变量,它总是与某种锁相关联,可以是外部传入的锁或是系统默认创建的锁.当几个条件变量共享一个锁时,你就应该自己传入一个锁.这个锁不需要你操心,Condition 类会 ...

  2. Python 线程同步变量,同步条件,列队

    条件变量同步 有一类线程需要满足条件之后才能够继续执行,Python提供了threading.Condition 对象用于条件变量线程的支持,它除了能提供RLock()或Lock()的方法外,还提供了 ...

  3. 深入解析条件变量(condition variables)

    深入解析条件变量 什么是条件变量(condition variables) 引用APUE中的一句话: Condition variables are another synchronization m ...

  4. [development][C] 条件变量(condition variables)的应用场景是什么

    产生这个问题的起因是这样的: ‎[:] ‎<‎tong‎>‎ lilydjwg: 主线程要启动N个子线程, 一个局部变量作为把同样的参数传入每一个子线程. 子线程在开始的十行会处理完参数. ...

  5. Linux组件封装(二)中条件变量Condition的封装

    条件变量主要用于实现线程之间的协作关系. pthread_cond_t常用的操作有: int pthread_cond_init(pthread_cond_t *cond, pthread_conda ...

  6. Linux 线程 条件变量

    一:条件变量 直接上最基本的两个函数,先抓主要矛盾: //等待条件 int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex ...

  7. [转] 条件变量(Condition Variable)详解

    http://www.wuzesheng.com/?p=1668 条件变量(Condtion Variable)是在多线程程序中用来实现“等待->唤醒”逻辑常用的方法.举个简单的例子,应用程序A ...

  8. 孤荷凌寒自学python第四十二天python线程控制之Condition对象

     孤荷凌寒自学python第四十二天python的线程同步之Condition对象 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 今天学习了Condition对象,发现它综合了Event对象 ...

  9. 条件变量(Condition Variable)详解

    条件变量(Condtion Variable)是在多线程程序中用来实现“等待->唤醒”逻辑常用的方法.举个简单的例子,应用程序A中包含两个线程t1和t2.t1需要在bool变量test_cond ...

随机推荐

  1. 二叉树的查找(前序、中序、后序、层序遍历)--biaobiao88

    建立一棵含有n个结点的二叉树,采用二叉链表存储: 输出前序.中序.后序..层序遍历该二叉树的遍历结果. 定义二叉树的数据类型——二叉树结点结构体BiNode.建立二叉链表可以采用扩展二叉树的一个遍历序 ...

  2. MySQL GROUP_CONCAT()函数 -- 字段合并查询

    在做查询的时候遇到一个问题,今天分享一下解决方法. 先看一下我想要什么效果. 清单名称类型要点,后面两列为清单步骤(外键表) 但我并不想让主表的内容重复那么多遍,于是 distinct去重.子查询.左 ...

  3. ReoGrid.Mvvm:ReoGrid绑定模型

    ReoGrid 是 C# 编写的.NET 电子表格控件(类似 Excel).支持单元格合并,边框样式,图案背景颜色,数据格式,冻结,公式,宏和脚本执行,表格事件等.支持 Winform\WPF. Re ...

  4. vue cli3.3 以上版本配置vue.config.js 及反向代理操作解决跨域操作

    const webpack = require('webpack') module.exports = { configureWebpack: { plugins: [ new webpack.Pro ...

  5. docker入门级详解

    Docker 1 docker安装 yum install docker [root@topcheer ~]# systemctl start docker [root@topcheer ~]# mk ...

  6. 设计模式C++描述----20.迭代器(Iterator)模式

    一. 举例说明 我们知道,在 STL 里提供 Iterator 来遍历 Vector 或者 List 数据结构. Iterator 模式也正是用来解决对一个聚合对象的遍历问题,将对聚合的遍历封装到一个 ...

  7. 关于高淇JAVA中SORM总结学习笔记详细个人解释

    代码来源于高淇JAVA教学视频 谢谢高淇老师的教学. 因为自己在学习的过程中发现了很多困难点,总结下希望对自己接下来学框架提升.给像我一样得初学者方便. SORM框架是一个简单的ORM,关系对象映射, ...

  8. JavaScript基础修炼(14)——WebRTC在浏览器中如何获得指定格式的PCM数据

    目录 一. PCM格式是什么 二. 浏览器中的音频采集处理 三. 需求实现 方案1--服务端FFmpeg实现编码 方案2--ScriptProcessorNode手动处理数据流 参考文献 示例代码托管 ...

  9. leetcode算法小题(1)

    题目描述: 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,你不能重复利用这个数 ...

  10. 虚拟机kali linux与windows主机共享文件

    在windows中我们可以直接拖拽文件,有的时候wmtools无效 很苦恼 从kali中托文件就不可以, 于是那就用到了共享文件夹 一.在虚拟机名称处右键,选择设置,会弹出一个设置框 二.选择选项-& ...