python并发编程之多进程、多线程、异步、协程、通信队列Queue和池Pool的实现和应用
什么是多任务?
简单地说,就是操作系统可以同时运行多个任务。实现多任务有多种方式,线程、进程、协程。
并行和并发的区别?
并发:指的是任务数多余cpu核数,通过操作系统的各种任务调度算法,实现用多个任务“一起”执行(实际上总有一些任务不在执行,因为切换任务的速度相当快,看上去一起执行而已)
并行:指的是任务数小于等于cpu核数,即任务真的是一起执行的
真的多任务叫并行,假的多任务叫并发。
我们来了解下python中的进程,线程以及协程!
从计算机硬件角度:
计算机的核心是CPU,承担了所有的计算任务。 一个CPU,在一个时间切片里只能运行一个程序。
从操作系统的角度:
进程和线程,都是一种CPU的执行单元。
进程:表示一个程序的上下文执行活动(打开、执行、保存...)
线程:进程执行程序时候的最小调度单位(执行a,执行b...),可以简单理解为同一进程中有多个计数器,每个线程的执行时间不确定,而每个进程的时间片相等,线程是操作系统调度执行的最小单位
一个程序至少有一个进程,一个进程至少有一个线程。
多进程/多线程:
表示可以同时执行多个任务,进程和线程的调度是由操作系统自动完成。
进程:每个进程都有自己独立的内存空间,不同进程之间的内存空间不共享。 进程之间的通信有操作系统传递,导致通讯效率低,切换开销大。进程是系统进行资源分配的最小单位
线程:一个进程可以有多个线程,所有线程共享进程的内存空间,通讯效率高,切换开销小。线程不能够独立执行,必须依存在进程中。共享意味着竞争,导致数据不安全,为了保护内存空间的数据安全,引入"互斥锁"。
一个线程在访问内存空间的时候,其他线程不允许访问,必须等待之前的线程访问结束,才能使用这个内存空间。
互斥锁:一种安全有序的让多个线程访问内存空间的机制。
多线程:
密集I/O任务(网络I/O,磁盘I/O,数据库I/O)使用多线程合适。 threading.Thread、multiprocessing.dummy 缺陷:同一个时间切片只能运行一个线程,不能做到高并行,但是可以做到高并发。
但是,使用多线程,必须考虑到GIL 全局解释器锁:线程的执行权限,在Python的进程里只有一个GIL。
一个线程需要执行任务,必须获取GIL。
好处:直接杜绝了多个线程访问内存空间的安全问题。 坏处:Python的多线程不是真正多线程,不能充分利用多核CPU的资源。
但是,在I/O阻塞的时候,解释器会释放GIL。
什么是GIL?
GIL并不是Python的特性,Python完全可以不依赖于GIL。GIL全称Global Interpreter Lock。它是在实现Python解析器(CPython)时所引入的一个概念。GIL无疑就是一把全局排他锁。
Python GIL其实是功能和性能之间权衡后的产物,它尤其存在的合理性,也有较难改变的客观因素。因为GIL的存在,只有IO Bound场景下得多线程会得到较好的性能,如果对并行计算性能较高的程序可以考虑把核心部分也成C模块,或者索性用其他语言实现
GIL在较长一段时间内将会继续存在,但是会不断对其进行改进。
线程创建步骤:
import threading
# 创建一个线程对象
t1 = threading.Thread(target=func_name, args=(num,), name=”子线程名字”)
# 创建一个线程并启动
t1.start()
# 等待子线程执行完毕之后再继续向下执行主线程
t1.join()
备注:主线程会等待子线程结束之后才会结束,主线程一死,子线程也会死。线程的调度是随机的,并没有先后顺序。
由于多线程之间共享全局变量就会导致出现资源竞争的问题,为了避免这种竞争出现,利用互斥锁可以实现线程同步。
实现方式:
# 创建锁
mutex = threading.Lock()
# 加锁
mutex.acquire()
# 释放锁
mutex.release()
多进程:
密集CPU任务,需要充分使用多核CPU资源(服务器,大量的并行计算)的时候,用多进程。 multiprocessing 缺陷:多个进程之间通信成本高,切换开销大。
进程创建步骤:
# 导入进程模块
import multiprocessing
# 创建一个进程的实力对象
P = Multiprocessing.Process(target=func_name, [args=(元组), kwargs={字典}])
# 创建并启动进程
p.start()
p.join(5)
通过Queue实现通信(注意进程和协程使用的队列不一样)
from queue import Queue # 线程、协程使用的队列
from multiprocessing import JoinableQueue as Queue # 进程使用的队列
q = Queue(maxsize=100)
item = {}
q.put_nowait(item) # 不等待直接放,队列满的时候会报错
q.put(item) # 放入数据,队列满的时候回等待
q.get_nowait() # 不等待直接取,队列空的时候会报错
q.get() # 取出数据,队列为空的时候会等待
q.qsize() # 获取队列中现存数据的个数
q.join() # 队列中维持了一个计数,计数不为0时候让主线程阻塞等待,队列计数为0的时候才会继续往后执行
q.task_done()
# put的时候计数+1,get不会-1,get需要和task_done 一起使用才会-1
注意:(多进程队列的使用非常特殊)
多进程中使用普通的队列模块会发生阻塞,对应的需要使用multiprocessing提供的JoinableQueue模块,其使用过程和在线程中使用的queue方法相同
如果是通过进程池创建的进程,那么队列的使用要用
multiprocessing.Manager().Queue()的方式,否则会报错。
进程池的实现步骤
# 导入进程池模块
From multiprocessing import Pool
# 定义进程池,最大进程池最大数
Po = Pool(3)
# 通过进程池调用目标 apply_async非阻塞,不会等待子进程结束;apply阻塞,会等待子进程结束才结束
po.apply_async(func,(传递给目标的参数元祖,))
# 关闭进程池
Po.close()
# 等待进程池执行完毕
Po.join()
注意:
线程如果要使用线程池:from multiprocessing.dummy import Pool
协程如果要使用协程池:from gevent.pool import Pool
协程:
又称微线程,在单线程上执行多个任务,用函数切换,开销极小。不通过操作系统调度,没有进程、线程的切换开销。genvent,monkey.patchall
多线程请求返回是无序的,那个线程有数据返回就处理那个线程,而协程返回的数据是有序的。
缺陷:单线程执行,处理密集CPU和本地磁盘IO的时候,性能较低。处理网络I/O性能还是比较高.
协程创建实例:
from gevent import monkey
import gevent
import random
import time
# 有耗时操作时需要
monkey.patch_all() # 将程序中用到的耗时操作的代码,换为gevent中自己实现的模块
def coroutine_work(coroutine_name):
for i in range(10):
print(coroutine_name, i)
time.sleep(random.random())
gevent.joinall([
gevent.spawn(coroutine_work, "work1"),
gevent.spawn(coroutine_work, "work2")
])
进程、线程、协程的区别和选择?
进程是资源分配的单位,真正执行代码的是线程,操作系统真正调度的是线程。
进程没有线程效率高,进程占用资源多,线程占用资源少,比线程更少的是协程。
协程依赖于线程、线程依赖于进程,进程一死线程必挂,线程一挂协程必死。
一般不用多进程,可以考虑使用多线程,如果多线程里面有很多网络请求,网络可能会有堵塞,此时用协程比较合适。
python并发编程之多进程、多线程、异步、协程、通信队列Queue和池Pool的实现和应用的更多相关文章
- Python并发编程二(多线程、协程、IO模型)
1.python并发编程之多线程(理论) 1.1线程概念 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程(流水线的工作需要电源,电源就相当于 ...
- python基础整理5——多进程多线程和协程
进程与线程 1.进程 我们电脑的应用程序,都是进程,假设我们用的电脑是单核的,cpu同时只能执行一个进程.当程序处于I/O阻塞的时候,CPU如果和程序一起等待,那就太浪费了,cpu会去执行其他的程序, ...
- Python并发编程06 /阻塞、异步调用/同步调用、异步回调函数、线程queue、事件event、协程
Python并发编程06 /阻塞.异步调用/同步调用.异步回调函数.线程queue.事件event.协程 目录 Python并发编程06 /阻塞.异步调用/同步调用.异步回调函数.线程queue.事件 ...
- Python并发编程__多进程
Python并发编程_多进程 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大 ...
- Python进阶(4)_进程与线程 (python并发编程之多进程)
一.python并发编程之多进程 1.1 multiprocessing模块介绍 由于GIL的存在,python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大 ...
- Python并发编程系列之多线程
1 引言 上一篇博文详细总结了Python进程的用法,这一篇博文来所以说Python中线程的用法.实际上,程序的运行都是以线程为基本单位的,每一个进程中都至少有一个线程(主线程),线程又可以创建子线程 ...
- python并发编程02 /多进程、进程的创建、进程PID、join方法、进程对象属性、守护进程
python并发编程02 /多进程.进程的创建.进程PID.join方法.进程对象属性.守护进程 目录 python并发编程02 /多进程.进程的创建.进程PID.join方法.进程对象属性.守护进程 ...
- 也说性能测试,顺便说python的多进程+多线程、协程
最近需要一个web系统进行接口性能测试,这里顺便说一下性能测试的步骤吧,大概如下 一.分析接口频率 根据系统的复杂程度,接口的数量有多有少,应该优先对那些频率高,数据库操作频繁的接口进行性能测试,所以 ...
- Python并发实践_02_通过yield实现协程
python中实现并发的方式有很多种,通过多进程并发可以真正利用多核资源,而多线程并发则实现了进程内资源的共享,然而Python中由于GIL的存在,多线程是没有办法真正实现多核资源的. 对于计算密集型 ...
随机推荐
- js 常用排序整理
排序: 1. 内部排序: (1). 交换排序: 1). 冒泡排序 稳定 一次比较相邻两个元素的大小,顺序错误的,将其位置互换 (从高位到低位 或者 从低位到高位) 初始版: var array = [ ...
- django模板templates详解(二)
1 总体结构 Django是MTV结构,即:Model, Template, View Model:定义数据的存储格式,并且提供了数据库访问的API. View:定义那些数据被显示,是业务逻辑处理 ...
- Laravel 教程 - 实战 iBrand 开源电商 API 系统
iBrand 简介 IYOYO 公司于2011年在上海创立.经过8年行业积累,IYOYO 坚信技术驱动商业革新,通过提供产品和服务助力中小企业向智能商业转型升级. 基于社交店商的核心价值,在2016年 ...
- JavaMelody监控spring、struts
前言 前面讲过了Javamelody的基本配置,如何使用Javamelody来监控JDBC以及SQL. 这里继续讲解一下如何监控struts和spring. 手码不易,转载请注明:xingoo 由于s ...
- python核心编程中网络爬虫的例子
#!/usr/bin/env python import cStringIO # import formatter # from htmllib import HTMLParser # We use ...
- SP1811 【LCS - Longest Common Substring】
\(SAM\)上匹配 我们就是需要找到两个串的最长公共子串 先对其中一个串建出\(SAM\),之后我们把另一个串放到上面跑 如果当前在\(SAM\)的状态是\(now\),下一个字符是\(c\),匹配 ...
- BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 【分块】
任意门:https://www.lydsy.com/JudgeOnline/problem.php?id=2002 2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: 10 ...
- idea 一次性自动导包
当复制粘贴一段纯文本代码时,许多类需要导包. 如图 使用optimize imports了,发还是没有办法导入未导入的包,只能删除未使用导包,这跟eclipse不一样,让人很不习惯,查了好多资料都没有 ...
- 【洛谷P1272】 重建道路
重建道路 题目链接 一场可怕的地震后,人们用N个牲口棚(1≤N≤150,编号1..N)重建了农夫John的牧场.由于人们没有时间建设多余的道路,所以现在从一个牲口棚到另一个牲口棚的道路是惟一的.因此, ...
- 【洛谷P1850】换教室[2016NOIP提高组]
换教室 期望DP 状态: f[i][j][0/1]表示前i节课 提交j个申请 第i个教室不申请/申请(为了确定当前教室,方便转移) 的最小期望 方程: f[i][j][0]=min(f[i-1][j] ...