Python线程协作threading.Condition实现过程解析


Posted in Python onMarch 12, 2020

领会下面这个示例吧,其实跟java中wait/nofity是一样一样的道理

import threading


# 条件变量,用于复杂的线程间同步锁
"""
需求:
  男:小姐姐,你好呀!
  女:哼,想泡老娘不成?
  男:对呀,想泡你
  女:滚蛋,门都没有!
  男:切,长这么丑, 还这么吊...
  女:关你鸟事!

"""
class Boy(threading.Thread):
  def __init__(self, name, condition):
    super().__init__(name=name)
    self.condition = condition

  def run(self):
    with self.condition:
      print("{}:小姐姐,你好呀!".format(self.name))
      self.condition.wait()
      self.condition.notify()

      print("{}:对呀,想泡你".format(self.name))
      self.condition.wait()
      self.condition.notify()

      print("{}:切,长这么丑, 还这么吊...".format(self.name))
      self.condition.wait()
      self.condition.notify()


class Girl(threading.Thread):
  def __init__(self, name, condition):
    super().__init__(name=name)
    self.condition = condition

  def run(self):
    with self.condition:
      print("{}:哼,想泡老娘不成?".format(self.name))
      self.condition.notify()
      self.condition.wait()

      print("{}:滚蛋,门都没有!".format(self.name))
      self.condition.notify()
      self.condition.wait()

      print("{}:关你鸟事!".format(self.name))
      self.condition.notify()
      self.condition.wait()


if __name__ == '__main__':
  condition = threading.Condition()
  boy_thread = Boy('男', condition)
  girl_thread = Girl('女', condition)

  boy_thread.start()
  girl_thread.start()

Condition的底层实现了__enter__和 __exit__协议.所以可以使用with上下文管理器

由Condition的__init__方法可知,它的底层也是维护了一个RLock锁

def __enter__(self):
    return self._lock.__enter__()
def __exit__(self, *args):
    return self._lock.__exit__(*args)
def __exit__(self, t, v, tb):
    self.release()
def release(self):
    """Release a lock, decrementing the recursion level.

    If after the decrement it is zero, reset the lock to unlocked (not owned
    by any thread), and if any other threads are blocked waiting for the
    lock to become unlocked, allow exactly one of them to proceed. If after
    the decrement the recursion level is still nonzero, the lock remains
    locked and owned by the calling thread.

    Only call this method when the calling thread owns the lock. A
    RuntimeError is raised if this method is called when the lock is
    unlocked.

    There is no return value.

    """
    if self._owner != get_ident():
      raise RuntimeError("cannot release un-acquired lock")
    self._count = count = self._count - 1
    if not count:
      self._owner = None
      self._block.release()

至于wait/notify是如何操作的,还是有点懵.....

wait()方法源码中这样三行代码

waiter = _allocate_lock() #从底层获取了一把锁,并非Lock锁
waiter.acquire()
self._waiters.append(waiter) # 然后将这个锁加入到_waiters(deque)中
saved_state = self._release_save() # 这是释放__enter__时的那把锁???

notify()方法源码

all_waiters = self._waiters  
waiters_to_notify = _deque(_islice(all_waiters, n))# 从_waiters中取出n个
if not waiters_to_notify:  # 如果是None,结束
   return
for waiter in waiters_to_notify: # 循环release
   waiter.release()
   try:
     all_waiters.remove(waiter) #从_waiters中移除
   except ValueError:
     pass

大体意思: wait先从底层创建锁,acquire, 放到一个deque中,然后释放掉with锁, notify时,从deque取拿出锁,release

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中pygame的mouse鼠标事件用法实例
Nov 11 Python
浅谈python中scipy.misc.logsumexp函数的运用场景
Jun 23 Python
利用python爬取软考试题之ip自动代理
Mar 28 Python
CentOS 6.5中安装Python 3.6.2的方法步骤
Dec 03 Python
Python3结合Dlib实现人脸识别和剪切
Jan 24 Python
Python内置模块logging用法实例分析
Feb 12 Python
不管你的Python报什么错,用这个模块就能正常运行
Sep 14 Python
一行代码让 Python 的运行速度提高100倍
Oct 08 Python
使用Django简单编写一个XSS平台的方法步骤
Mar 25 Python
Python单元和文档测试实例详解
Apr 11 Python
Python 常用日期处理 -- calendar 与 dateutil 模块的使用
Sep 02 Python
Python测试框架pytest高阶用法全面详解
Jun 01 Python
Python 实现网课实时监控自动签到、打卡功能
Mar 12 #Python
Python基于read(size)方法读取超大文件
Mar 12 #Python
Python函数生成器原理及使用详解
Mar 12 #Python
python deque模块简单使用代码实例
Mar 12 #Python
python中安装django模块的方法
Mar 12 #Python
python3 sorted 如何实现自定义排序标准
Mar 12 #Python
Python dict和defaultdict使用实例解析
Mar 12 #Python
You might like
PHP安装问题
2006/10/09 PHP
PHP对MongoDB[NoSQL]数据库的操作
2013/03/01 PHP
php ckeditor上传图片文件名乱码解决方法
2013/11/15 PHP
PHP基于php_imagick_st-Q8.dll实现JPG合成GIF图片的方法
2014/07/11 PHP
PHP使用file_get_content设置头信息的方法
2016/02/14 PHP
PHP实现查询两个数组中不同元素的方法
2016/02/23 PHP
JavaScript?Apple设备检测示例代码
2013/11/15 Javascript
jquery实现简单手风琴菜单效果实例
2015/06/13 Javascript
JavaScript转换与解析JSON方法实例详解
2015/11/24 Javascript
使用Javascript写的2048小游戏
2015/11/25 Javascript
基于JavaScript实现高德地图和百度地图提取行政区边界经纬度坐标
2016/01/22 Javascript
JavaScript:Date类型全面解析
2016/05/19 Javascript
jquery实现企业定位式导航效果
2018/01/01 jQuery
使用puppeteer爬取网站并抓出404无效链接
2018/12/20 Javascript
layer iframe 设置关闭按钮的方法
2019/09/12 Javascript
JavaScript enum枚举类型定义及使用方法
2020/05/15 Javascript
Element DateTimePicker日期时间选择器的使用示例
2020/07/27 Javascript
JS获取当前时间戳方法解析
2020/08/29 Javascript
[50:01]Ti4 冒泡赛第二天 NEWBEE vs Titan
2014/07/15 DOTA
[00:18]天涯墨客三技能展示
2018/08/25 DOTA
[51:39]DOTA2-DPC中国联赛 正赛 Magma vs LBZS BO3 第二场 2月7日
2021/03/11 DOTA
python正则表达式去掉数字中的逗号(python正则匹配逗号)
2013/12/25 Python
Python 多线程的实例详解
2017/09/07 Python
pandas数据分组和聚合操作方法
2018/04/11 Python
pytorch + visdom CNN处理自建图片数据集的方法
2018/06/04 Python
mac下pycharm设置python版本的图文教程
2018/06/13 Python
Python使用Pickle模块进行数据保存和读取的讲解
2019/04/09 Python
Python进阶之使用selenium爬取淘宝商品信息功能示例
2019/09/16 Python
解决pyinstaller打包运行程序时出现缺少plotly库问题
2020/06/02 Python
Farfetch巴西官网:奢侈品牌时尚购物平台
2020/10/19 全球购物
领导干部群众路线个人对照检查材料思想汇报
2014/09/30 职场文书
十佳少年事迹材料
2014/12/25 职场文书
班主任开场白
2015/06/01 职场文书
小区物业管理2015年度工作总结
2015/10/22 职场文书
springboot中rabbitmq实现消息可靠性机制详解
2021/09/25 Java/Android
Nginx的gzip相关介绍
2022/05/11 Servers