python之多进程and多线程
图文来自互联网
一、什么是进程和线程 (https://jq.qq.com/?_wv=1027&k=rX9CWKg4)
进程是分配资源的最小单位,线程是系统调度的最小单位。
当应用程序运行时最少会开启一个进程,此时计算机会为这个进程开辟独立的内存空间,不同的进程享有不同的空间,而一个CPU在同一时刻只能够运行一个进程,其他进程处于等待状态。
一个进程内部包括一个或者多个线程,这些线程共享此进程的内存空间与资源。相当于把一个任务又细分成若干个子任务,每个线程对应一个子任务。
二、多进程和多线程 (https://jq.qq.com/?_wv=1027&k=rX9CWKg4)
对于一个CPU来说,在同一时刻只能运行一个进程或者一个线程,而单核CPU往往是在进程或者线程间切换执行,每个进程或者线程得到一定的CPU时间,由于切换的速度很快,在我们看来是多个任务在并行执行(同一时刻多个任务在执行),但实际上是在并发执行(一段时间内多个任务在执行)。
单核CPU的并发往往涉及到进程或者线程的切换,进程的切换比线程的切换消耗更多的时间与资源。在单核CPU下,CPU密集的任务采用多进程或多线程不会提升性能,而在IO密集的任务中可以提升(IO阻塞时CPU空闲)。
而多核CPU就可以做到同时执行多个进程或者多个进程,也就是并行运算。在拥有多个CPU的情况下,往往使用多进程或者多线程的模式执行多个任务。
三、python中的多进程和多线程
1、多进程
def Test(pid):
print("当前进程{}:{}".format(pid, os.getpid()))
for i in range(1000000000):
pass
if __name__ == '__main__':
#单进程
start = time.time()
for i in range(2):
Test(i)
end = time.time()
print((end - start))
单进程输出结果如图1:
def Test(pid):
print("当前子进程{}:{}".format(pid, os.getpid()))
for i in range(100000000):
pass
if __name__ == '__main__':
#多进程
print("父进程:{}".format(os.getpid()))
start = time.time()
pool = Pool(processes=2)
pid = [i for i in range(2)]
pool.map(Test, pid)
pool.close()
pool.join()
end = time.time()
print((end - start))
多进程输出结果如图2:
从输出结果可以看出都是执行两次for循环,多进程比单进程减少了近乎一半的时间(这里使用了两个进程),并且查看CPU情况可以看出多进程利用了多个CPU。
python中的多进程可以利用mulitiprocess模块的Pool类创建,利用Pool的map方法来运行子进程。一般多进程的执行如下代码:
def Test(pid):
print("当前子进程{}:{}".format(pid, os.getpid()))
for i in range(100000000):
pass
if __name__ == '__main__':
#多进程
print("父进程:{}".format(os.getpid()))
pool = Pool(processes=2)
pid = [i for i in range(4)]
pool.map(Test, pid)
pool.close()
pool.join()
1、利用Pool类创建一个进程池,processes声明在进程池中最多可以运行几个子进程,不声明的情况下会自动根据CPU数量来设定,原则上进程池容量不超过CPU数量。(出于资源的考虑,不要创建过多的进程)
2、声明一个可迭代的变量,该变量的长度决定要执行多少次子进程。
3、利用map()方法执行多进程,map方法两个参数,第一个参数是多进程执行的方法名,第二个参数是第二步声明的可迭代变量,里面的每一个元素是方法所需的参数。 这里需要注意几个点:1)进程池满的时候请求会等待,以上述代码为例,声明了一个容量为2的进程池,但是可迭代变量有4个,那么在执行的时候会先创建两个子进程,此时进程池已满,等待有子进程执行完成,才继续处理请求;
2) 子进程处理完一个请求后,会利用已经创建好的子进程继续处理新的请求而不会重新创建进程。
从图3可以看出上述两个点,如果同时处理4个进程,那么只需要2秒钟,这里是分成两次处理,花费了4秒,并且两次处理使用的子进程号都相同。
3)map会将每个子进程的返回值汇总成一个列表返回。
4、在所有请求处理结束后使用close()方法关闭进程池不再接受请求。
5、使用join()方法让主进程阻塞,等待子进程退出,join()方法要放在close()方法之后,防止主进程在子进程结束之前退出。
2、多线程
python的多线程模块用threading类进行创建
import time
import threading
import os
count = 0
def change(n):
global count
count = count + n
count = count - n
def run(n):
print("当前子线程:{}".format(threading.current_thread().name))
for i in range(10000000):
change(n)
if __name__ == '__main__':
print("主线程:{}".format(threading.current_thread().name))
thread_1 = threading.Thread(target=run, args=(3,))
thread_2 = threading.Thread(target=run, args=(10,))
thread_1.start()
thread_2.start()
thread_1.join()
thread_2.join()
print(count)
程序执行会创建一个进程,进程会默认启动一个主线程,使用threading.Thread()创建子线程;target为要执行的函数;args传入函数需要的参数;start()启动子线程,join()阻塞主线程先运行子线程。 由于变量由多个线程共享,任何一个线程都可以对于变量进行修改,如果同时多个线程修改变量就会出现错误。
上面的程序在理论上的结果应该为0,但运行结果如图4
出现这个结果的原因就是多个线程同时对于变量修改,在赋值时出现错误,具体解释见多线程
解决这个问题就是在修改变量的时候加锁,这样就可以避免出现多个线程同时修改变量。
import time
import threading
import os
count = 0
lock = threading.Lock()
def change(n):
global count
count = count + n
count = count - n
def run(n):
print("当前子线程:{}".format(threading.current_thread().name))
for i in range(10000000):
# lock.acquire()
# try:
change(n)
# finally:
# lock.release()
if __name__ == '__main__':
print("主线程:{}".format(threading.current_thread().name))
thread_1 = threading.Thread(target=run, args=(3,))
thread_2 = threading.Thread(target=run, args=(10,))
thread_1.start()
thread_2.start()
thread_1.join()
thread_2.join()
print(count)
python中的线程需要先获取GIL(Global Interpreter Lock)锁才能继续运行,每一个进程仅有一个GIL,线程在获取到GIL之后执行100字节码或者遇到IO中断时才会释放GIL,这样在CPU密集的任务中,即使有多个CPU,多线程也是不能够利用多个CPU来提高速率,甚至可能会因为竞争GIL导致速率慢于单线程。所以对于CPU密集任务往往使用多进程,IO密集任务使用多线程。
参考资料
大江狗:一文看懂Python多进程与多线程编程(工作学习面试必读)
多线程
python之多进程and多线程的更多相关文章
- Python 中多进程、多线程、协程
进程: 一个运行的程序(代码)就是一个进程,没有运行的代码叫程序,进程是系统资源分配的最小单位,进程拥有自己独立的内存空间,所以进程间数据不共享.开销大. 线程: 调度执行的最小单位,也叫执行路径,不 ...
- Python的多进程和多线程
进程和线程 进程是系统进行资源分配的最小单位,线程是系统进行调度执行的最小单位: 一个应用程序至少包含一个进程,一个进程至少包含一个线程: 每个进程在执行过程中拥有独立的内存空间,而一个进程中的线程之 ...
- Python之多进程和多线程
目标: 1.os.fork简单示例 2.使用os.fork多进程测试IP是否在线 3.使用os.fork多进程解决tcpserver多客户端连接问题 4.多线程测试IP地址是否在线 1.os.fork ...
- 【python】多进程、多线程、序列
一.多进程 1.子进程永远返回0,而父进程返回子进程的ID.这样做的理由是,一个父进程可以fork出很多子进程,所以,父进程要记下每个子进程的ID,而子进程只需要调用getppid()就可以拿到父进程 ...
- 【转】Python中的GIL、多进程和多线程
转自:http://lesliezhu.github.io/public/2015-04-20-python-multi-process-thread.html 目录 1. GIL(Global In ...
- Python中的多进程与多线程(二)
在上一章中,学习了Python多进程编程的一些基本方法:使用跨平台多进程模块multiprocessing提供的Process.Pool.Queue.Lock.Pipe等类,实现子进程创建.进程池(批 ...
- python采用 多进程/多线程/协程 写爬虫以及性能对比,牛逼的分分钟就将一个网站爬下来!
首先我们来了解下python中的进程,线程以及协程! 从计算机硬件角度: 计算机的核心是CPU,承担了所有的计算任务.一个CPU,在一个时间切片里只能运行一个程序. 从操作系统的角度: 进程和线程,都 ...
- 在python中单线程,多线程,多进程对CPU的利用率实测以及GIL原理分析
首先关于在python中单线程,多线程,多进程对cpu的利用率实测如下: 单线程,多线程,多进程测试代码使用死循环. 1)单线程: 2)多线程: 3)多进程: 查看cpu使用效率: 开始观察分别执行时 ...
- 学习笔记--python中使用多进程、多线程加速文本预处理
一.任务描述 最近尝试自行构建skip-gram模型训练word2vec词向量表.其中有一步需要统计各词汇的出现频率,截取出现频率最高的10000个词汇进行保留,形成常用词词典.对于这个问题,我建立了 ...
随机推荐
- redis在物理机部署模式下如何进行资源[cpu、网卡]隔离
上周末晚上运营做直播,业务代码不规范,访问1个redis竟然把1台服务器的网卡打满了,这台服务器上的其他redis服务都受到了影响.之前没有做这方面的预案,当时又没有空闲的机器可以迁移,在当时一点办法 ...
- git 将本地文件推送到远程分支的分支
1. 新建文件夹复制远程分支 2. 切换到远程分支 3. 推送到远程 添加到暂存区,先运行 " git add . " 查看文件状态 在运 ...
- python学习-Day22
目录 今日内容详细 hashlib加密模块 什么是加密 加密算法 加密的使用 基本使用 指定算法(md5) 将明文数据传递给算法对象 获取加密之后的密文数据 加密补充 加盐处理 动态加盐 加密应用场景 ...
- Spring Boot 启动源码解析结合Spring Bean生命周期分析
转载请注明出处: 1.SpringBoot 源码执行流程图 2. 创建SpringApplication 应用,在构造函数中推断启动应用类型,并进行spring boot自动装配 public sta ...
- 面试官问:浏览器输入 URL 回车之后发生了什么?
一个执着于技术的公众号 前言 这个问题已经是老生常谈了,更是经常被作为面试的压轴题出现,网上也有很多文章,但最近闲的无聊,然后就自己做了一篇笔记,感觉比之前理解更透彻了. 注意:本文的步骤是建立在,请 ...
- JZ009乘积小于k的子数组
title: 乘积小于k的子数组 题目描述 题目链接:乘积小于k的子数组.剑指offer009 解题思路 注意: 一开始的乘积k值就是小的,随着右边窗口移动才会不断增大 怎么样的条件才能更新左窗口:当 ...
- DOM操作标签、事件绑定、jQuery框架/类库
DOM操作标签 ''' 在起变量名的时候 如果该变量指向的是一个标签 那么建议使用 xxxEle eg:aEle\pEle\divEle\spanEle ''' # 动态创建一个a标签并添加到页面指定 ...
- Centos 7以上安装Docker (亲测有效)
一.安装前的准备 我的环境是VMware15虚拟机安装的Centos7,Linux内核是3.10.0-1062.4.1.e17.x86_64 1. 用root账户登录查看操作系统内核版本及相关信息 [ ...
- 2022管家婆工贸版ERP T3 V22.0工厂管理软件单机网络版无限用户免狗软件可定制
管家婆工贸版是一款针对国内中小加工企业开发的管理软件,软件以财务管理为核心,集采购.销售.存货.生产.工资.固定资产.账务管理等模块于一体,对企业的信息进行监控,实现对企业物流.资金流.信息流和生产成 ...
- Oceanbase读写分离方案探索与优化
[作者] 许金柱,携程资深DBA,专注于分布式数据库研究及运维. 台枫,携程高级DBA,主要负责MySQL和OceanBase的运维. [前言] 读写分离,是一种将数据库的查询操作和写入操作分离 ...