原文链接

Python中多线程与多进程的区别

Multiprocessing V.S. Threading

摘要

如果你不想读整篇文章,这里有你所需要的本文精华:

  • 如果你的程序运行效率瓶颈在于网络传输时延,那么你可以使用多线程。
  • 如果你的程序运行效率瓶颈在于CPU数量,那么你就可以尝试多进程。

之所以写出这一部分指引是因为我发现在其他关于多线程与多进程的区别的介绍中,大部分信息都十分晦涩难懂。而我们往往需要花很多时间去研究得很深入,到头来发现对自己如何去解决自己手上的实际问题还是没有什么帮助。

什么是多线程?为什么我们要用多线程?

我们都知道,python是一个线性的语言,然而当你需要更大的处理性能时,python多线程模块就有他的作用了。即使Python无法用于CPU的并行计算,他在处理I/O操作时仍然很棒,比如在做多线程爬虫的时候,大部分时间处理器都处于空闲状态等待数据的进入。

python多线程实际上改变了多线程的规则,这是因为许多脚本都会花大部分的时间处理与网络/数据之间的I/O或等待数据从远端传入。由于下载的数据不需要是连续的(比如爬取不同的网站信息),处理器就能够并行地从不同数据源下载数据最后把它们拼接起来。然而对于比较集中的CPU操作,threading模块可能就没有那么大的收益了。

多线程threading使用方法

我们可以直接从python的标准库中引入多线程模块threading:

import threading
from queue import Queue
import time

同时你可以通过target参数定义线程调用的函数,通过args为该函数传参,用start方法启动线程,如下demo:

def testThread(num):print(num)if __name__ == '__main__':for i in range(5):t = threading.Thread(target=testThread, arg=(i, ))t.start()

如果你从没见过if __name__ == '__main__':这条语句:这条语句是一个能够保证代码在内部嵌套的基本的方法,他只会在你直接运行该脚本的时候执行,而不会在被import时调用。

锁机制

通常情况下,我们希望多线程能够使用或更改同一个变量的时候不发生冲突,这个时候我们就会用到锁机制。任何时候当一个函数需要更改一个变量的数值,他就会锁住这个变量,而当其他变量需要使用时,必须等待这个变量被当前锁住他的线程释放出来。

假如有两个函数需要迭代地处理一个变量。这个时候锁机制就能够保证一次只能有一个函数获得这个变量的使用权限,对这个变量进行相关的操作,并且在他未释放这个变量之前都不会有其他函数具有访问权限。

在使用python threading模块时,在使用打印功能时经常会发生文本输出的混淆(数据也可能会损坏)。这个时候可以尝试用打印锁来保证一次只有一个线程在进行打印操作。

print_lock = threading.Lock()def threadTest():# when this exits, the print_lock is releasedwith print_lock:print(worker)def threader():while True:# get the job from the front of the queuethreadTest(q.get())q.task_done()q = Queue()
for x in range(5):thread = threading.Thread(target = threader)# this ensures the thread will die when the main thread dies# can set t.daemon to False if you want it to keep runningt.daemon = Truet.start()for job in range(10):q.put(job)

上面这个例子我们定义了10个需要完成的任务以及5个线程去处理他们。

多线程并非适用所有的场景

现在很多关于多线程的介绍都会忽略掉使用这些方法时的缺点。然而了解多线程在使用过程中的优点和缺点其实是非常重要的:

  1. 管理多线程有额外的开销,因此在简单的任务中使用他并不好。
  2. 同时它会让程序更为复杂,在debug的时候也会更麻烦。

什么是多进程?它与多线程的区别是什么?

在没有多进程(Multi-processing)的概念时,由于GIL(Global Interpreter Lock)机制的影响(详解GIL),python无法最大化系统的性能。实际上,由于python非常古老,开发者在开发的过程时并没有考虑过会使用在多cpu上,在当时的情况下,因为python并不是thread-safe的,所以需要有一个在访问python对象时的全局锁。即使这个GIL锁并不是完美的,但是它确实是一种非常有效的内存管理机制。

多进程能够让程序绕过GIL锁,去并行地处理程序,并能够更充分地使用cpu。虽然它与threading模块本质不同,但是语法上非常相似。多进程库会为每个进程提供各自的解释器和GIL锁。

在多线程上会发生的问题(如数据混淆、死锁等)在多进程上并不会发生。这是因为在多进程上,不同的线程直接的存储不共享,因此也就不会发生同时不同空间同时更改同一内存空间这一情况。

多进程Multiprocessing的使用方法

import multiprocessing
def spawn():print('test!')if __name__ == '__main__':for i in range(5):p = multiprocessing.Process(target=spawn)p.start()

如果你有一个共享的数据库,你需要确保在开始新流程之前等待相关流程完成。
这时只需要在上面的程序中进行一点小小的改动:

for i in range(5):p = multiprocessing.Process(target=spawn)p.start()p.join() # this line allows you to wait for processes

如果需要往函数中传参,方法也很简单:

import multiprocessing
def spawn(num):print(num)if __name__ == '__main__':for i in range(25):## right herep = multiprocessing.Process(target=spawn, args=(i,))p.start()

这时一个很好的例子,因为没有了p.join(),这个程序的输出并不是按照你既定的顺序。

多进程Multiprocessing的缺点

跟多线程一样,多进程同样也有一些自己的缺点。当你在选择的时候需要参考自己的场景及他们二者各自的缺点来确定该用哪一种模式:

  1. 在进程间进行数据的交互会产生额外的I/O开销。
  2. 整个内存空间被复制到每个子进程中,这样对于比较复杂的程序造成的额外开销也很大。

两者分别在何种场景下应用?

  • 如果你的程序有大量与数据交互/网络交互,可以使用多线程,因为程序时间瓶颈不在于GIL而是在I/O,这时多线程的小开销就比多进程更实用。
  • 如果你的程序有图形界面GUI,使用多线程,GIL锁会帮助你让你的UI线程不会产生死锁等问题。
  • 如果你的程序的运行效率与CPU密切相关的,即瓶颈在于计算等情况,且有多核可用时,就可以考虑用多进程提高效率。

python多线程(Multiprocessing)与多线程(Multithreading)区别优缺点最详细解释相关推荐

  1. Python之pandas:pandas.set_option函数的参数详细解释

    Python之pandas:pandas.set_option函数的参数详细解释 目录 pandas.set_option函数的参数解释 函数API:pandas.set_option pandas. ...

  2. python multithreading_操作系统OS,Python - 多进程(multiprocessing)、多线程(multithreading)...

    多进程(multiprocessing) 参考: 1. 多进程概念 multiprocessing is a package that supports spawning processes usin ...

  3. 史上最全的python的web开发和网络编程【附属详细解释+案例】

    文章目录 1. IP 地址 2. 端口 2.1 端口 介绍 2.2 端口号 介绍 3. TCP 3.1 为什么要用TCP? 3.2 TCP 和 UDP 的 解释 3.3 TCP 步骤 和 特点 4. ...

  4. python用户画像建模_求用户画像的详细解释、建模方法及算法模型

    先给你一个传送门,目测是一个腾讯内部的培训资料:https://bbs.pinggu.org/thread-3868699-1-1.html 该文档我看了,虽然比较浅,但内容相当实在--目前大家谈起用 ...

  5. string 相等 java_java中string相等问题(==与.equal的具体区别。求详细解释)

    展开全部 这要和String的JVM内部工作原理相结合! 比如:String s1="accp" Java内部将此62616964757a686964616fe58685e5aeb ...

  6. python【Multiprocessing and threading】深入浅出多进程和多线程

    文章目录 1 概念 2 添加进程 Process 3 存储进程输出 Queue 4 效率对比 threading & multiprocessing 5 进程池 Pool 6 共享内存 sha ...

  7. python lock_python多线程Lock和RLock的区别

    python多线程Lock和RLock的区别 1. 两种锁的不同 1.1 定义 为了确保对共享资源的访问,python提供了两种锁,一个是上一篇提到的Lock,还有一个就是RLock,他们的区别在于: ...

  8. python爬虫进程和线程的区别_熬了两个通宵写的!终于把多线程和多进程彻底讲明白了!...

    我们知道,在一台计算机中,我们可以同时打开许多软件,比如同时浏览网页.听音乐.打字等等,看似非常正常.但仔细想想,为什么计算机可以做到这么多软件同时运行呢?这就涉及到计算机中的两个重要概念:多进程和多 ...

  9. Python 多进程开发与多线程开发

    我们先来了解什么是进程? 程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程.程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本:进程 ...

最新文章

  1. pxe安装linux后命令不可用,CentOS7下的PXE无人值守系统安装(亲测成功)
  2. ifdown eth0 idup eth0 ifdown --exclude=l0 -a ifup --exclude=lo -a
  3. 【自动驾驶】31.【相机外参标定】、【相机障碍物后处理】【地面的2D点反投影到3D】的过程对比
  4. 计算机视觉算法——目标检测网络总结
  5. leetcode 42. 接雨水 思考分析(暴力、动态规划、双指针、单调栈)
  6. python3openpyxl无法打开文件_Python3 处理excel文件(openpyxl库)
  7. mysql数据库表名大小写敏感_Mysql数据库名和表名的大小写敏感性问题
  8. mgr未同步 mysql_MySQL MGR如何修复数据不一致的节点
  9. Windows系统单网卡配置双IP双网关
  10. Transformer的中年危机
  11. Java Class的文件结构
  12. python time函数的功能_Python中Python时间模块的常用功能,Pythontime,函数
  13. SVN版本管理的回滚(SmartSVN)
  14. 零基础学前端系列教程 | 和前端谈恋爱的第002天——约会邀请
  15. Hexo+Github轻松搭建个人博客
  16. 大学生如何培育计算机思维,计算机思维下的计算机课程改革思路探索
  17. TCP基于窗口的端到端的拥塞控制机制
  18. Android游戏:弹弹球(打砖块)
  19. WebStrom代码中出现浅黄色背景
  20. 圣思园——Java SE Lesson 5

热门文章

  1. mysql常用汉字库_MYSQL 常用总结【基础】
  2. php json_decode gbk,,json_decode含gbk字串
  3. http协议各个版本之解说
  4. 实训1_获取产业数据并存储_预处理与简单分析
  5. 《吴恩达深度学习》学习笔记002_神经网络的编程基础(Basics of Neural Network programming)
  6. google earth pro无法链接服务器的问题
  7. 连续语音信号的短时倒谱分析及其参数用途
  8. Unity3D基础案例-双人坦克
  9. 必读论文 | 卷积神经网络百篇经典论文推荐
  10. 无法下载图片 App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insec