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实现批量获取指定文件夹下的所有文件的厂商信息
Sep 28 Python
在Python的Flask框架中实现全文搜索功能
Apr 20 Python
详尽讲述用Python的Django框架测试驱动开发的教程
Apr 22 Python
使用Py2Exe for Python3创建自己的exe程序示例
Oct 31 Python
Python实现合并两个有序链表的方法示例
Jan 31 Python
python的pytest框架之命令行参数详解(下)
Jun 27 Python
详解Python 4.0 预计推出的新功能
Jul 26 Python
Python 中的 global 标识对变量作用域的影响
Aug 12 Python
Python 迭代,for...in遍历,迭代原理与应用示例
Oct 12 Python
python脚本实现mp4中的音频提取并保存在原目录
Feb 27 Python
python读取文件指定行内容实例讲解
Mar 02 Python
OpenCV-Python直方图均衡化实现图像去雾
Jun 07 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
thinkphp四种url访问方式详解
2014/11/28 PHP
PHP中使用array函数新建一个数组
2015/11/19 PHP
php提交过来的数据生成为txt文件
2016/04/28 PHP
Laravel 5.2 文档 数据库 ―― 起步介绍
2019/10/21 PHP
事件模型在各浏览器中存在差异
2010/10/20 Javascript
通过js为元素添加多项样式,浏览器全兼容写法
2014/08/30 Javascript
解决JavaScript数字精度丢失问题的方法
2015/12/03 Javascript
基于javaScript的this指向总结
2017/07/22 Javascript
原生javascript自定义input[type=radio]效果示例
2019/08/27 Javascript
ES6使用 Array.includes 处理多重条件用法实例分析
2020/03/02 Javascript
分享一款超好用的JavaScript 打包压缩工具
2020/04/26 Javascript
微信小程序实现列表的横向滑动方式
2020/07/15 Javascript
linux环境下安装pyramid和新建项目的步骤
2013/11/27 Python
itchat接口使用示例
2017/10/23 Python
Python定时器实例代码
2017/11/01 Python
django之session与分页(实例讲解)
2017/11/13 Python
解决python selenium3启动不了firefox的问题
2018/10/13 Python
解决Pytorch 训练与测试时爆显存(out of memory)的问题
2019/08/20 Python
Django 创建后台,配置sqlite3教程
2019/11/18 Python
Python 实现将某一列设置为str类型
2020/07/14 Python
深入了解Python 变量作用域
2020/07/24 Python
html5 初试 indexedDB(推荐)
2016/07/21 HTML / CSS
韩国知名的家庭购物网站:CJmall
2016/08/01 全球购物
Tarte Cosmetics官网:美国最受欢迎的化妆品公司之一
2017/08/24 全球购物
Giglio美国站:意大利奢侈品购物网
2018/02/10 全球购物
27个经典Linux面试题及答案,你知道几个?
2014/03/11 面试题
某公司部分笔试题
2013/11/05 面试题
瀑布模型都有哪些优缺点
2014/06/23 面试题
应届生服务员求职信
2013/10/31 职场文书
如何做好总经理助理
2013/11/12 职场文书
校园奶茶店创业计划书
2014/01/23 职场文书
大学生先进事迹材料
2014/02/16 职场文书
电子商务专业应届毕业生求职信
2014/06/21 职场文书
拾金不昧表扬稿大全
2015/05/05 职场文书
go语言中json数据的读取和写出操作
2021/04/28 Golang
Win10防火墙白名单怎么设置?Win10添加防火墙白名单方法
2022/04/06 数码科技