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的Django框架代码的一些示例
Apr 20 Python
Python通过正则表达式选取callback的方法
Jul 18 Python
Using Django with GAE Python 后台抓取多个网站的页面全文
Feb 17 Python
TF-IDF与余弦相似性的应用(一) 自动提取关键词
Dec 21 Python
python实现自动发送邮件发送多人、群发、多附件的示例
Jan 23 Python
Python request设置HTTPS代理代码解析
Feb 12 Python
Python发展简史 Python来历
May 14 Python
如何获取Python简单for循环索引
Nov 21 Python
基于Python检测动态物体颜色过程解析
Dec 04 Python
python 使用while循环输出*组成的菱形实例
Apr 12 Python
python删除某个目录文件夹的方法
May 26 Python
python smtplib发送多个email联系人的实现
Oct 09 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代码
2007/03/08 PHP
ubuntu 编译安装php 5.3.3+memcache的方法
2010/08/05 PHP
PHP获取浏览器信息类和客户端地理位置的2个方法
2014/04/24 PHP
C/S和B/S两种架构区别与优缺点分析
2014/10/23 PHP
php实现的redis缓存类定义与使用方法示例
2017/08/09 PHP
cookie.js 加载顺序问题怎么才有效
2013/07/31 Javascript
JQuery判断radio是否选中并获取选中值的示例代码
2014/10/17 Javascript
原生js和jQuery随意改变div属性style的名称和值
2014/10/22 Javascript
jQuery中is()方法用法实例
2015/01/06 Javascript
比较常见的javascript中定义函数的区别
2015/11/09 Javascript
js格式化输入框内金额、银行卡号
2016/02/01 Javascript
vue中如何动态绑定图片,vue中通过data返回图片路径的方法
2018/02/07 Javascript
微信小程序引入Vant组件库过程解析
2019/08/06 Javascript
Nodejs libuv运行原理详解
2019/08/21 NodeJs
使用Webpack提升Vue.js应用程序的4种方法(翻译)
2019/10/09 Javascript
从源码角度来回答keep-alive组件的缓存原理
2021/01/18 Javascript
[41:37]DOTA2北京网鱼队选拔赛——冲击职业之路
2015/04/13 DOTA
在Python函数中输入任意数量参数的实例
2019/07/16 Python
python3+django2开发一个简单的人员管理系统过程详解
2019/07/23 Python
django 解决自定义序列化返回处理数据为null的问题
2020/05/20 Python
python怎么判断素数
2020/07/01 Python
英国最大的电子产品和家电零售企业:Currys PC World
2016/09/24 全球购物
Nike挪威官网:Nike.com (NO)
2018/11/26 全球购物
经典的班主任推荐信
2013/10/28 职场文书
银行会计财务工作个人的自我评价
2013/10/29 职场文书
应届实习生的自我评价范文
2014/01/05 职场文书
负责人任命书范本
2014/06/04 职场文书
优秀共青团员事迹材料
2014/12/25 职场文书
个人自荐书范文
2015/03/09 职场文书
基层组织建设年活动总结
2015/05/09 职场文书
金正昆讲礼仪观后感
2015/06/11 职场文书
初中美术教学反思
2016/02/17 职场文书
导游词之上海豫园
2019/10/24 职场文书
Jsonp劫持学习
2021/04/01 PHP
CSS完成视差滚动效果
2021/04/27 HTML / CSS
tree shaking对打包体积优化及作用
2022/07/07 Java/Android