Python threading模块condition原理及运行流程详解


Posted in Python onOctober 05, 2020

Condition的处理流程如下:

首先acquire一个条件变量,然后判断一些条件。

  • 如果条件不满足则wait;
  • 如果条件满足,进行一些处理改变条件后,通过notify方法通知其他线程,其他处于wait状态的线程接到通知后会重新判断条件。
  • 不断的重复这一过程,从而解决复杂的同步问题。

Condition的基本原理如下:

可以认为Condition对象维护了一个锁(Lock/RLock)和一个waiting池。线程通过acquire获得Condition对象,当调用wait方法时,线程会释放Condition内部的锁并进入blocked状态,同时在waiting池中记录这个线程。当调用notify方法时,Condition对象会从waiting池中挑选一个线程,通知其调用acquire方法尝试取到锁。

Condition对象的构造函数可以接受一个Lock/RLock对象作为参数,如果没有指定,则Condition对象会在内部自行创建一个RLock。

除了notify方法外,Condition对象还提供了notifyAll方法,可以通知waiting池中的所有线程尝试acquire内部锁。由于上述机制,处于waiting状态的线程只能通过notify方法唤醒,所以notifyAll的作用在于防止有的线程永远处于沉默状态。

演示条件变量同步的经典问题是生产者与消费者问题:假设有一群生产者(Producer)和一群消费者(Consumer)通过一个市场来交互产品。生产者的”策略“是如果市场上剩余的产品少于1000个,那么就生产100个产品放到市场上;而消费者的”策略“是如果市场上剩余产品的数量多余100个,那么就消费3个产品。用Condition解决生产者与消费者问题的代码如下:

# -*- coding: utf-8 -*-
"""
Created on Wed Nov 28 17:15:29 2018

@author: 18665
"""

import threading
import time

class Producer(threading.Thread):
  # 生产者函数
  def run(self):
    global count
    while True:
      if con.acquire():
        # 当count 小于等于1000 的时候进行生产
        if count > 1000:
          con.wait()
        else:
          count = count+100
          msg = self.name+' produce 100, count=' + str(count)
          print(msg)
          # 完成生成后唤醒waiting状态的线程,
          # 从waiting池中挑选一个线程,通知其调用acquire方法尝试取到锁
          con.notify()
        con.release()
        time.sleep(1)

class Consumer(threading.Thread):
  # 消费者函数
  def run(self):
    global count
    while True:
      # 当count 大于等于100的时候进行消费
      if con.acquire():
        if count < 100:
          con.wait()
        
        else:
          count = count-5
          msg = self.name+' consume 5, count='+str(count)
          print(msg)
          con.notify()
          # 完成生成后唤醒waiting状态的线程,
          # 从waiting池中挑选一个线程,通知其调用acquire方法尝试取到锁
        con.release()
        time.sleep(1)

count = 500
con = threading.Condition()

def test():
  for i in range(2):
    p = Producer()
    p.start()
  for i in range(5):
    c = Consumer()
    c.start()
if __name__ == '__main__':
  test()

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

Python 相关文章推荐
Python入门篇之字典
Oct 17 Python
Python使用Beautiful Soup包编写爬虫时的一些关键点
Jan 20 Python
Python的collections模块中的OrderedDict有序字典
Jul 07 Python
python实现读取并显示图片的两种方法
Jan 13 Python
Python实现PS滤镜Fish lens图像扭曲效果示例
Jan 29 Python
详解PyTorch批训练及优化器比较
Apr 28 Python
python中使用zip函数出现错误的原因
Sep 28 Python
python将一组数分成每3个一组的实例
Nov 14 Python
python模块之subprocess模块级方法的使用
Mar 26 Python
Python使用sax模块解析XML文件示例
Apr 04 Python
python2和python3应该学哪个(python3.6与python3.7的选择)
Oct 01 Python
python Matplotlib基础--如何添加文本和标注
Jan 26 Python
Python urllib库如何添加headers过程解析
Oct 05 #Python
Python3获取cookie常用三种方案
Oct 05 #Python
Python collections.deque双边队列原理详解
Oct 05 #Python
Python全局变量与global关键字常见错误解决方案
Oct 05 #Python
Python定时任务框架APScheduler原理及常用代码
Oct 05 #Python
Python xmltodict模块安装及代码实例
Oct 05 #Python
Python pathlib模块使用方法及实例解析
Oct 05 #Python
You might like
Oracle 常见问题解答
2006/10/09 PHP
php 图片上传类代码
2009/07/17 PHP
PHP面向对象的进阶学习(抽像类、接口、final、类常量)
2012/05/07 PHP
php生成RSS订阅的方法
2015/02/13 PHP
codeigniter实现get分页的方法
2015/07/10 PHP
Symfony2学习笔记之插件格式分析
2016/03/17 PHP
PHP安装GeoIP扩展根据IP获取地理位置及计算距离的方法
2016/07/01 PHP
PHP不使用递归的无限级分类简单实例
2016/11/05 PHP
JS中Iframe之间传值及子页面与父页面应用
2013/03/11 Javascript
JS:window.onload的使用介绍
2013/11/13 Javascript
用JavaScript实现页面重定向功能的教程
2015/06/04 Javascript
简介JavaScript中的push()方法的使用
2015/06/09 Javascript
轻松学习jQuery插件EasyUI EasyUI实现拖动基本操作
2015/11/30 Javascript
超级简易的JS计算器实例讲解(实现加减乘除)
2017/08/08 Javascript
vue打包使用Nginx代理解决跨域问题
2018/08/27 Javascript
vue 使某个组件不被 keep-alive 缓存的方法
2018/09/21 Javascript
mpvue+vant app搭建微信小程序的方法步骤
2019/02/11 Javascript
微信小程序template模版的使用方法
2019/04/13 Javascript
js+css3实现简单时钟特效
2020/09/13 Javascript
原生js实现表格循环滚动
2020/11/24 Javascript
Python判断Abundant Number的方法
2015/06/15 Python
python+django加载静态网页模板解析
2017/12/12 Python
Python读取数据集并消除数据中的空行方法
2018/07/12 Python
Windows下安装Scrapy
2018/10/17 Python
python处理excel绘制雷达图
2019/10/18 Python
Python中Pyspider爬虫框架的基本使用详解
2021/01/27 Python
阿根廷旅游网站:almundo阿根廷
2018/02/12 全球购物
军用级手机壳,专为冒险而建:Zizo Wireless
2019/08/07 全球购物
造价工程师个人求职信
2013/09/21 职场文书
四查四看剖析材料
2014/02/14 职场文书
教育技术职业规划范文
2014/03/04 职场文书
高中生期中考试失利检讨书
2014/10/23 职场文书
幼儿园教研工作总结2015
2015/05/12 职场文书
工作转正自我鉴定范文
2019/06/21 职场文书
vue-cropper插件实现图片截取上传组件封装
2021/05/27 Vue.js
Redis基本数据类型哈希Hash常用操作命令
2022/06/01 Redis