Python 多线程多进程

前提

我是参考 Github Python 100 天的文章写的,再结合自己的小练习,总结

最近在面大厂,发现许多大厂都会问 Python 的多线程、多进程,所以我觉得很有必要总结学习下。

什么是进程

操作系统中执行的一个程序,类似微信、QQ,每个程序都是一个进程

概念

它是 CPU 最小资源分配单元

操作系统会给进程分配内存空间,每个进程都会有自己的地址空间、数据栈以及其他用于跟踪进程执行的辅助数据

操作系统管理所有进程的执行,为它们合理的分配资源

fork、spawn

进程可以通过 fork、spawn 的方式来创建新的进程来执行其他任务

不过新的进程有自己独立的内存空间、数据栈

因此不同进程间需要通过通信机制(IPC)来实现数据共享

常见通信机制

管道

信号

套接字

共享内存区

什么是线程

进程中可以拥有多个并发的执行线索

它是 CPU 最小调度的执行单元

特点

同一个进程下的线程共享相同的上下文

相对于进程来说,线程间的信息共享和通信更加容易

单核 CPU 系统注意事项

真正的并发是不可能的

因为在某个时刻,CPU 只能运行唯一的一个线程

多个线程共享了 CPU 的执行时间

多线程的好处

提升程序的性能和改善用户体验

今天日常使用的软件几乎都用到了多线程

多线程的坏处

站在其他进程的角度,多线程的程序对其他程序并不友好,因为它占用了更多的 CPU 执行时间,导致- - 其他程序无法获得足够的 CPU 执行时间

编写和调试多线程的程序对开发者要求较高

Python 实现并发编程的方式

多进程

多线程

多进程+多线程

Python 中的多进程

Linux 下的 fork 函数

Linux 操作系统上提供了 fork() 系统调用来创建进程

调用 fork() 函数的是父进程

创建的是子进程

子进程是父进程的拷贝

但子进程有自己的 PID

fork() 函数非常特殊,它会返回两次,父进程中调用 fork() 会返回子进程的 PID,子进程中调用 fork() 得到的都是0

Python 提供的 fork 函数

os 模块提供了 fork()

Window 下没有 fork() 的调用

实现跨平台的多进程变成,可以使用 multiprocessing 模块的 Process 类来创建子进程

还提供了更高级的封装,例如批量启动进程的进程池 pool、用于进程间同喜你的队列 Queue 和管道 Pipe

使用多进程和不使用多进程的区别(写代码)

不使用多进程

fromrandom import randintfromtimeimporttime, sleepdef download_task(filename):print('开始下载%s...'% filename)    time_to_download =randint(5,10)sleep(time_to_download)print('%s下载完成! 耗费了%d秒'% (filename, time_to_download))defmain():    start =time()download_task('Python从入门到住院.pdf')download_task('Peking Hot.avi')    end =time()print('总共耗费了%.2f秒.'% (end - start))if __name__ =='__main__':main()

执行结果

开始下载Python从入门到住院.pdf...Python从入门到住院.pdf下载完成! 耗费了10秒开始下载PekingHot.avi...PekingHot.avi下载完成! 耗费了9秒总共耗费了19.02秒.

可以看到需要先等第一个文件下载完才能下载第二个文件,效率很低

使用多进程

fromrandom import randintfromtimeimporttime, sleepfrommultiprocessing import Processdef download_task(filename):print('开始下载%s...'% filename)    time_to_download =randint(5,10)sleep(time_to_download)print('%s下载完成! 耗费了%d秒'% (filename, time_to_download))defmain2():    start =time()    p1 =Process(target=download_task,args=("Python从入门到住院.pdf",))    p1.start()    p2 =Process(target=download_task, args=("Peking Hot.avi",))    p2.start()    p1.join()    p2.join()    end =time()print('总共耗费了%.2f秒.'% (end - start))if __name__ =='__main__':main2()

执行结果

开始下载Python从入门到住院.pdf...开始下载PekingHot.avi...Python从入门到住院.pdf下载完成! 耗费了6秒PekingHot.avi下载完成! 耗费了10秒总共耗费了10.17秒.

两个任务同时执行,总耗时不再是两个任务的时间总和

知识点

Process:通过 Process 类创建进程对象

target:通过 target 参数传入一个函数名来表示进程启动后要执行的代码

args:是一个元组,代表传递给函数的参数列表

start:Process 的 start() 方法来启动进程

join:Process 的 join() 方法表示等待进程执行结束,才会往下执行

Python 中的多线程

前言

推荐 threading 模块来实现多线程编程,它提供了更好的面向对象封装

多线程的实现方式

#!/usr/bin/env python# -*- coding: utf-8 -*-"""

__title__  =

__Time__  = 2021/3/19 18:17

__Author__ = 小菠萝测试笔记

__Blog__  = https://www.cnblogs.com/poloyy/

"""fromrandomimportrandintfromthreadingimportThreadfromtimeimporttime, sleepdefdownload_task(filename):print('开始下载%s...'% filename)    time_to_download = randint(5,10)    sleep(time_to_download)print('%s下载完成! 耗费了%d秒'% (filename, time_to_download))defmain3():start = time()    p1 = Thread(target=download_task,args=("Python从入门到住院.pdf",))    p1.start()    p2 = Process(target=download_task, args=("Peking Hot.avi",))    p2.start()    p1.join()    p2.join()    end = time()print('总共耗费了%.2f秒.'% (end - start))if__name__ =='__main__':    main3()

执行结果

开始下载Python从入门到住院.pdf...开始下载PekingHot.avi...PekingHot.avi下载完成! 耗费了6秒Python从入门到住院.pdf下载完成! 耗费了8秒总共耗费了8.01秒.

一样执行效率高很多

自定义线程类

#!/usr/bin/env python# -*- coding: utf-8 -*-"""

__title__  =

__Time__  = 2021/3/19 18:17

__Author__ = 小菠萝测试笔记

__Blog__  = https://www.cnblogs.com/poloyy/

"""fromrandomimportrandintfromthreadingimportThreadfromtimeimporttime, sleepclassdownLoadTask(Thread):def__init__(self,filename):super().__init__()        self.filename = filenamedefrun(self) ->None:print('开始下载%s...'% self.filename)        time_to_download = randint(5,10)        sleep(time_to_download)print('%s下载完成! 耗费了%d秒'% (self.filename, time_to_download))defmain3():start = time()    p1 = downLoadTask("Python从入门到住院.pdf")    p2 = downLoadTask("Peking Hot.avi")    p1.start()    p2.start()    p1.join()    p2.join()    end = time()print('总共耗费了%.2f秒.'% (end - start))if__name__ =='__main__':    main3()

执行结果

开始下载Python从入门到住院.pdf...开始下载PekingHot.avi...PekingHot.avi下载完成! 耗费了6秒Python从入门到住院.pdf下载完成! 耗费了9秒总共耗费了9.00秒.

也是一样的高效运行

重点知识:start 和 run 方法的区别

比较点startrun

作用启动线程,获取 CPU 时间片运行线程指定的代码块

线程状态可运行状态运行状态

调用次数一个线程只能调用一次可以重复调用

运行线程创建了一个子线程,线程名是自己命名的在主线程中调用了一个普通函数

注意点想用多线程,必须调用 start()

Python 中的协程

什么是协程

Python 中,单线程+异步 I/O 的编程模型

协程的优势

极高的执行效率

子程序切换不是线程切换,而是由程序本身控制,没有线程切换的开销

不需要多线程的所机制,只有一个线程,所以不存在同时写变量冲突,在协程中控制共享资源不用加锁,只需要判断状态就好了,所以执行效率比多线程高很多

重点

要充分利用 CPU 的多核特性,应该使用多进程+协程的方式

待更新

EOF

本文作者:小菠萝测试笔记

本文原文链接:https://www.cnblogs.com/poloyy/p/14565951.html

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

本文转自:SDK社区(sdk.cn)是一个中立的社区,这里有多样的前端知识,有丰富的api,有爱学习的人工智能开发者,有风趣幽默的开发者带你学python,还有未来火热的鸿蒙,当各种元素组合在一起,让我们一起脑洞大开共同打造专业、好玩、有价值的开发者社区,帮助开发者实现自我价值!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 222,104评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,816评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,697评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,836评论 1 298
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,851评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,441评论 1 310
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,992评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,899评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,457评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,529评论 3 341
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,664评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,346评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,025评论 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,511评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,611评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,081评论 3 377
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,675评论 2 359