python的多线程基础设施

2024-05-16 02:08

本文主要是介绍python的多线程基础设施,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

当我们在使用线程时,存在以下基本的多线程编程的概念:

  • lock:多个线程访问临界资源时,为满足线程安全必须保证访问临界资源的代码同一时刻仅有一个线程执行。
  • condition:传递消息的工具。线程中的条件,不满足条件就wait,获得条件就执行。
  • wait():在条件实例中可用的wait()。
  • notify() / notifyAll():在条件实例中可用的notify()通知一个其他等待的线程或其他所有线程,看当前线程对临界资源状态的改变是否与所有线程有关,一般只需要通知一个其他线程即可。

python提供的多线程基础设施与其他语言的类似,都是在上述线程环境下的实现。下面是多线程实现的生产者消费者模型。

1、锁的使用

from threading import Thread, Lock
import time
import randomqueue = []
lock = Lock()class ProducerThread(Thread):def run(self):nums = range(5)while True:num = random.choice(nums)lock.acquire()queue.append(num)print "Produced", num lock.release()time.sleep(random.random())class ConsumerThread(Thread):def run(self):while True:lock.acquire()if not queue:print "Nothing in queue, but consumer will try to consume"num = queue.pop(0)print "Consumed", num lock.release()time.sleep(random.random())ProducerThread().start()
ConsumerThread().start()

lock提供的release和lock方法将对临界资源queue的访问代码进行了保护,使得不会存在同时访问临界资源的问题。但是,仅仅使用锁会出现问题,因为多个线程之间需要传递消息,(注意,传递数据使用全局变量临界资源就可以,但传递消息必须要新的工具),需要使用线程传递消息的工具condition来实现。

2、传递消息

python的多线程传递消息机制condition内含了lock,其acquire()和release()方法在内部调用了lock的acquire()和release()。所以在python中可以用condiction实例取代lock实例,但lock的行为不会改变。

from threading import Thread, Condition
import random
import timequeue = []
MAX_NUM = 10
queue_avalible = Condition()class Producer(Thread):def run(self):nums = range(MAX_NUM)while True:num = random.choice(nums)queue_avalible.acquire()if len(queue) == MAX_NUM:print "queue is full, waiting for consuming"queue_avalible.wait()queue.append(num)print "Produced ", numqueue_avalible.notify()queue_avalible.release()class Consumer(Thread):def run(self):nums = range(MAX_NUM)while True:queue_avalible.acquire()if len(queue) == 0:print "queue is empty, waiting for producing"queue_avalible.wait()num = queue.pop(0)print "Consumed ", numqueue_avalible.notify()queue_avalible.release()Producer().start()
Consumer().start()

上述使用的是Condition内部自带的lock来进行加锁解锁,但是这样有一个需要注意的问题,调用notify的时候,其他等待的线程并不能马上运行,因为使用的是同一个queue_avalible,当前调用notify之后再调用release之后其他等待线程才能运行。下面是python文档的原文:

Note: the notify() and notifyAll() methods don’t release the lock; this means that the thread or threads awakened will not return from their wait() call immediately, but only when the thread that called notify() or notifyAll() finally relinquishes ownership of the lock.
An awakened thread does not actually return from its wait() call until it can reacquire the lock. Since notify() does not release the lock, its caller should.

3、Queue封装

python中的Queue模块对多线程操作的队列进行了封装,非常方便的使用它能快速构建程序。

The Queue module implements multi-producer, multi-consumer queues. It is especially useful in threaded programming when information must be exchanged safely between multiple threads. The Queue class in this module implements all the required locking semantics.

支持如下三种队列:

  • class Queue.Queue(maxsize=0)
    FIFO队列类。 maxsize 是最大长度,达到上限之后调用put操作会被阻塞。小于等于0的maxsize将是无限大的队列。
  • class Queue.LifoQueue(maxsize=0)
    LIFO队列类。 maxsize 是最大长度,达到上限之后调用put操作会被阻塞。小于等于0的maxsize将是无限大的队列。
  • class Queue.PriorityQueue(maxsize=0)
    优先队列类。 maxsize 是最大长度,达到上限之后调用put操作会被阻塞。小于等于0的maxsize将是无限大的队列。

另外提供两种异常:
Queue.Empty
当队列为空是,调用了non-blocking get() (or get_nowait()) 函数时发生
- Queue.Full
当队列满之后,调用了 non-blocking put() (or put_nowait()) 函数时发生

提供的方法如下:
- Queue.qsize():返回队列大小
- Queue.empty()
- Queue.full()
- Queue.get([block[, timeout]]):获取一个值,如果block为true并且timeout为None,就会在队列为空时阻塞只到有元素;如果timeout为正整数,将会最多阻塞设置的时间,然后raises Empty exception。如果block为False,那么直接在有元素时返回该元素,否则直接抛出Empty异常。
- Queue.get_nowait():相当于get(false)
- Queue.put(item[, block[, timeout]]):插入一个值,如果block为true并且timeout为None,就会在队列满了之后阻塞只到有空闲位置;如果timeout为正整数,将会最多阻塞设置的时间,然后raises Full exception。如果block为False,那么直接在有空闲位置时插入,否则直接抛出Full异常。
- Queue.put_nowait(item):相当于put(item, false)
- Queue.task_done():检查后台线程是否完成
- Queue.join():等待后台线程完成

这篇关于python的多线程基础设施的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/993571

相关文章

Django开发时如何避免频繁发送短信验证码(python图文代码)

《Django开发时如何避免频繁发送短信验证码(python图文代码)》Django开发时,为防止频繁发送验证码,后端需用Redis限制请求频率,结合管道技术提升效率,通过生产者消费者模式解耦业务逻辑... 目录避免频繁发送 验证码1. www.chinasem.cn避免频繁发送 验证码逻辑分析2. 避免频繁

精选20个好玩又实用的的Python实战项目(有图文代码)

《精选20个好玩又实用的的Python实战项目(有图文代码)》文章介绍了20个实用Python项目,涵盖游戏开发、工具应用、图像处理、机器学习等,使用Tkinter、PIL、OpenCV、Kivy等库... 目录① 猜字游戏② 闹钟③ 骰子模拟器④ 二维码⑤ 语言检测⑥ 加密和解密⑦ URL缩短⑧ 音乐播放

python panda库从基础到高级操作分析

《pythonpanda库从基础到高级操作分析》本文介绍了Pandas库的核心功能,包括处理结构化数据的Series和DataFrame数据结构,数据读取、清洗、分组聚合、合并、时间序列分析及大数据... 目录1. Pandas 概述2. 基本操作:数据读取与查看3. 索引操作:精准定位数据4. Group

Python pandas库自学超详细教程

《Pythonpandas库自学超详细教程》文章介绍了Pandas库的基本功能、安装方法及核心操作,涵盖数据导入(CSV/Excel等)、数据结构(Series、DataFrame)、数据清洗、转换... 目录一、什么是Pandas库(1)、Pandas 应用(2)、Pandas 功能(3)、数据结构二、安

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

Python安装Pandas库的两种方法

《Python安装Pandas库的两种方法》本文介绍了三种安装PythonPandas库的方法,通过cmd命令行安装并解决版本冲突,手动下载whl文件安装,更换国内镜像源加速下载,最后建议用pipli... 目录方法一:cmd命令行执行pip install pandas方法二:找到pandas下载库,然后

Python实现网格交易策略的过程

《Python实现网格交易策略的过程》本文讲解Python网格交易策略,利用ccxt获取加密货币数据及backtrader回测,通过设定网格节点,低买高卖获利,适合震荡行情,下面跟我一起看看我们的第一... 网格交易是一种经典的量化交易策略,其核心思想是在价格上下预设多个“网格”,当价格触发特定网格时执行买

Python标准库之数据压缩和存档的应用详解

《Python标准库之数据压缩和存档的应用详解》在数据处理与存储领域,压缩和存档是提升效率的关键技术,Python标准库提供了一套完整的工具链,下面小编就来和大家简单介绍一下吧... 目录一、核心模块架构与设计哲学二、关键模块深度解析1.tarfile:专业级归档工具2.zipfile:跨平台归档首选3.

使用Python构建智能BAT文件生成器的完美解决方案

《使用Python构建智能BAT文件生成器的完美解决方案》这篇文章主要为大家详细介绍了如何使用wxPython构建一个智能的BAT文件生成器,它不仅能够为Python脚本生成启动脚本,还提供了完整的文... 目录引言运行效果图项目背景与需求分析核心需求技术选型核心功能实现1. 数据库设计2. 界面布局设计3

Python进行JSON和Excel文件转换处理指南

《Python进行JSON和Excel文件转换处理指南》在数据交换与系统集成中,JSON与Excel是两种极为常见的数据格式,本文将介绍如何使用Python实现将JSON转换为格式化的Excel文件,... 目录将 jsON 导入为格式化 Excel将 Excel 导出为结构化 JSON处理嵌套 JSON: