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设计模式之代理模式实例
Apr 26 Python
python使用锁访问共享变量实例解析
Feb 08 Python
Python实现判断给定列表是否有重复元素的方法
Apr 11 Python
python版本的仿windows计划任务工具
Apr 30 Python
Python3爬虫全国地址信息
Jan 05 Python
Python Multiprocessing多进程 使用tqdm显示进度条的实现
Aug 13 Python
Pytorch实现GoogLeNet的方法
Aug 18 Python
浅析python表达式4+0.5值的数据类型
Feb 26 Python
浅谈Python中threading join和setDaemon用法及区别说明
May 02 Python
Python urllib.request对象案例解析
May 11 Python
基于Keras的格式化输出Loss实现方式
Jun 17 Python
keras分类模型中的输入数据与标签的维度实例
Jul 03 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编程最快明白》第六讲:Mysql数据库操作
2010/11/01 PHP
实现PHP多线程异步请求的3种方法
2014/01/17 PHP
PHP文件操作实例总结
2016/09/27 PHP
redis+php实现微博(三)微博列表功能详解
2019/09/23 PHP
JavaScript在IE和Firefox(火狐)的不兼容问题解决方法小结
2010/04/13 Javascript
某人初学javascript的时候写的学习笔记
2010/12/30 Javascript
js setTimeout 常见问题小结
2013/08/13 Javascript
jQuery 获取和设置select下拉框的值实现代码
2013/11/08 Javascript
在浏览器中打开或关闭JavaScript的方法
2015/06/03 Javascript
jQuery实现的多级下拉菜单效果代码
2015/08/24 Javascript
JavaScript使用DeviceOne开发实战(二) 生成调试安装包
2015/12/01 Javascript
理解Angular数据双向绑定
2016/01/10 Javascript
jQuery如何防止Ajax重复提交
2016/10/14 Javascript
prototype与__proto__区别详细介绍
2017/01/09 Javascript
判断横屏竖屏(三种)
2017/02/13 Javascript
深入探究node之Transform
2017/07/20 Javascript
Angularjs实现页面模板清除的方法
2018/07/20 Javascript
服务端预渲染之Nuxt(使用篇)
2019/04/08 Javascript
vue-cli3添加模式配置多环境变量的方法
2019/06/05 Javascript
《javascript设计模式》学习笔记一:Javascript面向对象程序设计对象成员的定义分析
2020/04/07 Javascript
Python中使用wxPython开发的一个简易笔记本程序实例
2015/02/08 Python
Python设计模式之命令模式简单示例
2018/01/10 Python
python3 unicode列表转换为中文的实例
2018/10/26 Python
Python 多线程不加锁分块读取文件的方法
2018/12/11 Python
HTML5实现移动端点击翻牌功能
2020/10/23 HTML / CSS
Whistles官网:英国女装品牌
2020/08/14 全球购物
澳洲的UGG雪地靴超级市场:Uggs.com.au
2020/04/06 全球购物
小学生自我评价范文
2014/01/25 职场文书
企业管理毕业生求职信范文
2014/03/07 职场文书
食堂采购员岗位职责
2014/03/17 职场文书
酒店工程部岗位职责
2015/02/12 职场文书
一般纳税人申请报告
2015/05/18 职场文书
信息简报范文
2015/07/21 职场文书
2016教师六五普法学习心得体会
2016/01/21 职场文书
golang实现浏览器导出excel文件功能
2022/03/25 Golang