最新要闻
- 总投资约306亿元 南阳105个项目纳入2023年全省卫生健康“三个一批”项目
- 男子人肉占车位 雷克萨斯直接倒车撞 网友:解气但不提倡
- 49db智能降噪!iQOO TWS 1评测:戴上它 整个世界都安静了
- 被污名化太久!腾讯张立军:游戏强力推动芯片、AI等技术发展
- 2999元智商税“圾皇” 买完要被朋友嘲笑两年半
- 近期,四大生肖事业连走上坡路,收入节节高升,财运亨通
- 把充电速度带入“5G时代” 理想纯电车型搭载5C电池:不到十分钟续航400km
- iPad mini唯一对手!新款联想拯救者Y700性能确认:搭载骁龙8+
- 李玟演唱《战歌》竟成绝唱 《斗罗大陆2》动画片头缅怀
- 都不买英伟达难受了:RTX 4080大降价 首次跌破1000美元!降到多少你会买?
- 我国新能源汽车达1620万辆 仅汽车保有量1/20 增长潜力巨大
- 男生考上985研究生辞掉车企上万月薪工作:父母很支持
- 比亚迪汉同门兄弟!海豹DM-i要来了:20万级大杀四方
- 续航90公里 宝马发布全新电动摩托车CE 02:最高车速95km/h
- 潼关县两馆一中心预计今年12月建成
- 打击乐器都有什么(打击乐器有哪些)
手机
英国房地产因利率上升陷入困境 房价正以2011年来最快速度下跌
宁夏评选出上半年10名“宁夏好人” 95后消防员因敬业奉献入选
- 英国房地产因利率上升陷入困境 房价正以2011年来最快速度下跌
- 宁夏评选出上半年10名“宁夏好人” 95后消防员因敬业奉献入选
- 离婚时共同债务应该怎么处理?
- 华为云盘古大模型3.0正式发布
- 支持自动长文生成,WPS AI发布:基于大语言模型的智能办公助手
- 《街头霸王6》全球总销量突破200万份 卡普空再次为其玩家送上礼物
家电
Python多任务教程:进程、线程、协程
1.进程
进程是一个具有一定独立功能的程序在一个数据集上的一次动态执行的过程,是操作系统进行资源分配和调度的一个独立单位,是应用程序运行的载体。进程是一种抽象的概念,从来没有统一的标准定义。进程一般由程序、数据集合和进程控制块三部分组成。程序用于描述进程要完成的功能,是控制进程执行的指令集;数据集合是程序在执行时所需要的数据和工作区;程序控制块包含进程的描述信息和控制信息是进程存在的唯一标志。
进程具有的特征:
(资料图片)
- 动态性:进程是程序的一次执行过程,是临时的,有生命期的,是动态产生,动态消亡的。
- 并发性:任何进程都可以同其他进程一起并发执行。
- 独立性:进程是系统进行资源分配和调度的一个独立单位。
- 结构性:进程由程序、数据和进程控制块三部分组成。
实现多进程
import multiprocessingimport timedef run1(sleep_time): while True: print("-- 1 --") time.sleep(sleep_time)def run2(sleep_time): while True: print("-- 2 --") time.sleep(sleep_time)def main(): # 创建进程对象。 # target:指定线程调用的函数名。注:等号后跟方法名不能加括号,如果加了也能执行函数但threading功能无效 # args:指定调用函数时传递的参数。注:args是一个数组变量参数,只传一个参数时,需要在参数后面添加逗号 p1 = multiprocessing.Process(target=run1, args=(1,)) p2 = multiprocessing.Process(target=run2, args=(1,)) # 启用子进程 p1.start() p2.start() # join方法等待子进程执行结束 p1.join() p2.join() print("子进程结束")if __name__ == "__main__": main()
运行上面代码,查看任务管理器python的启动进程数。代码中只启动了两个子进程,但是为什么有3个python进程?这是因为,python会创建一个主进程(第1个进程),当运行到p1.start()时会创建一个子进程(第2个进程),当运行到p2.start()时又会创建一个子进程(第3个进程)
2.进程池
进程的创建和删除是需要消耗计算机资源的,如果有大量任务需要多进程完成,则可能需要频繁的创建删除进程,这会给计算机带来较多的资源消耗。进程池的出现解决了这个问题,它的原理是创建适当的进程放入进程池,等待待处理的事件,当处理完事件后进程不会销毁,仍然在进程池中等待处理其他事件,直到事件全部处理完毕,进程退出。 进程的复用降低了资源的消耗。
实现进程池
import time, osfrom multiprocessing import Pooldef worker(msg): start_time = time.time() print(F"{msg}开始执行,进程pid为{os.getpid()}") time.sleep(1) end_time = time.time() print(F"{msg}执行完毕,耗时{end_time - start_time}")def main(): po = Pool(3) # 定义进程池最大进程数为3 for i in range(10): # 每次循环会用空闲出的子进程调用目标 po.apply_async(worker, args=(i,)) # 若调用的函数报错,进程池中不会打印报错信息 po.close() # 关闭进程池,关闭后,不再接收新的目标 po.join() # 等待进程池中所有子进程执行完,必须放在close()之后。若没有join()操作,主进程执行完后直接关闭 print("--end--")if __name__ == "__main__": main()
3.线程
在早期的操作系统中并没有线程的概念,进程是拥有资源和独立运行的最小单位,也是程序执行的最小单位。任务调度采用的是时间片轮转的抢占式调度方式,而进程是任务调度的最小单位,每个进程有各自独立的一块内存,使得各个进程之间内存地址相互隔离。后来,随着计算机的发展,对CPU的要求越来越高,进程之间的切换开销较大,已经无法满足越来越复杂的程序的要求了。于是就发明了线程,线程是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单位。一个进程可以有一个或多个线程,各个线程之间共享程序的内存空间(也就是所在进程的内存空间)。一个标准的线程由线程ID,当前指令指针PC,寄存器和堆栈组成。而进程由内存空间(代码,数据,进程空间,打开的文件)和一个或多个线程组成。
实现多线程
import timeimport threadingdef say(sleep_time): for i in range(5): print(f"说{i+1}下") time.sleep(sleep_time)def dance(): for i in range(10): print(f"跳{i+1}下") time.sleep(1)def main(): # 创建线程对象 # target:指定线程调用的函数名。注:等号后跟方法名不能加括号,如果加了也能执行函数但threading功能无效 # args:指定调用函数时传递的参数。注:args是一个数组变量参数,只传一个参数时,需要在参数后面添加逗号 t1 = threading.Thread(target=say, args=(1,)) t2 = threading.Thread(target=dance) # 启动线程 t1.start() t2.start() # 查看正在运行的线程 while True: now_threading = threading.enumerate() print(now_threading) # 当子线程全部运行结束后,仅剩1个主线程 if len(now_threading) <= 1: break time.sleep(1)if __name__ == "__main__": main()
多线程的资源竞争问题
因为多线程共享全局变量,当线程还没执行完当前任务,操作系统就自动轮流调度执行其他任务,就可能会产生资源竞争的问题。
比如下例中,执行 g_num+=1 时,会将其分成3步执行:1.取值;2.运算;3.保存运算结果,在CPU执行任务时,若刚运行1 2 步就交替执行下一个任务,再返回来保存结果,因为共享全局变量,此时运算结果可能已被重新赋值。
import timeimport threadingg_num = 0def sum1(num): global g_num for i in range(num): g_num += 1 print(F"sum1:{g_num}")def sum2(num): global g_num for i in range(num): g_num += 1 print(F"sum2:{g_num}")def main(): t1 = threading.Thread(target=sum1, args=(1000000,)) t2 = threading.Thread(target=sum2, args=(1000000,)) t1.start() t2.start() time.sleep(2) print(g_num) # 执行后,预期结果为2000000;实际不是if __name__ == "__main__": main()
执行结果从结果可以看出,sum1和sum2不为1000000,总和不为2000000,这就是上面说的资源竞争问题
互斥锁解决资源竞争问题
import threadingimport time# 定义一个全局变量g_num = 0# 创建一个互斥锁,默认是没有上锁的mutex = threading.Lock()def sum1(num): global g_num # mutex.acquire() # 若在此处上锁,要等下面循环执行完才会解锁,若循环时间太长,会导致另外的线程堵塞等待。 for i in range(num): # 上锁,如果之前没有被上锁,那么此时上锁成功。 上锁原则:一般对产生资源竞争的代码上锁。如果上锁之前 已经被上锁了,那么此时会堵塞在这里,直到 这个锁被解开为止。 mutex.acquire() g_num += 1 # 解锁 mutex.release() print("-----in test1 g_num=%d----" % g_num)def sum2(num): global g_num for i in range(num): mutex.acquire() g_num += 1 mutex.release() print("-----in test2 g_num=%d=----" % g_num)def main(): t1 = threading.Thread(target=sum1, args=(1000000,)) t2 = threading.Thread(target=sum2, args=(1000000,)) t1.start() t2.start() # 等待上面的2个线程执行完毕.... time.sleep(2) print("-----in main Thread g_num = %d---" % g_num)if __name__ == "__main__": main()
运行结果
死锁
在线程间共享多个资源的时候,如果两个线程分别占用部分资源并且同时等待对方的资源,就会造成死锁。尽管死锁很少发生,但一旦发生就会造成应用停止响应。下面看一个死锁例子。
import timeimport threading# 创建多个锁mutexA = threading.Lock()mutexB = threading.Lock()def print1(): mutexA.acquire() time.sleep(2) # 等待B锁稳定 print("打印A1") mutexB.acquire() print("打印B1") mutexB.release() mutexA.release()def print2(): mutexB.acquire() time.sleep(1) # 等待A锁稳定 print("打印B2") mutexA.acquire() print("打印A2") mutexA.release() mutexB.release()def main(): t1 = threading.Thread(target=print1) t2 = threading.Thread(target=print2) t1.start() t2.start()if __name__ == "__main__": main()
执行结果避免死索办法:1、添加超时时间;2、银行家算法(让锁按预期上锁和解锁)
4.协程
协程,又称微线程。协程的作用是在执行函数A时可以随时中断去执行函数B,然后中断函数B继续执行函数A(可以自由切换)。但这一过程并不是函数调用,这一整个过程看似像多线程,然而协程只有一个线程执行。
协程的优势:
- 执行效率极高,因为子程序切换(函数)不是线程切换,由程序自身控制,没有切换线程的开销。所以与多线程相比,线程的数量越多,协程性能的优势越明显。
- 不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在控制共享资源时也不需要加锁,因此执行效率高很多。
gevent
gevent是第三方库,通过 greenlet 实现 coroutine,创建、调度的开销比 线程(thread) 还小,因此程序内部的 执行流 效率高。
其基本思想是:当一个greenlet遇到IO操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO。
gevent常用方法:
- gevent.spawn() 创建一个普通的Greenlet对象并切换
- gevent.spawn_later(seconds=3) 延时创建一个普通的Greenlet对象并切换
- gevent.spawn_raw() 创建的协程对象属于一个组
- gevent.getcurrent() 返回当前正在执行的greenlet
- gevent.joinall(jobs) 将协程任务添加到事件循环,接收一个任务列表
- gevent.wait() 可以替代join函数等待循环结束,也可以传入协程对象列表
- gevent.kill() 杀死一个协程
- gevent.killall() 杀死一个协程列表里的所有协程
- monkey.patch_all() 非常重要,会自动将python的一些标准模块替换成gevent框架
import geventdef task(n): for i in range(n): print(gevent.getcurrent(), i)if __name__ == "__main__": g1 = gevent.spawn(task, 3) g2 = gevent.spawn(task, 3) g3 = gevent.spawn(task, 3) g1.join() g2.join() g3.join()
运行结果可以看到3个greenlet是依次运行而不是交替运行。要让greenlet交替运行,可以通过gevent.sleep()交出控制权:
import geventdef task(n): for i in range(n): print(gevent.getcurrent(), i) gevent.sleep(1)if __name__ == "__main__": g1 = gevent.spawn(task, 3) g2 = gevent.spawn(task, 3) g3 = gevent.spawn(task, 3) g1.join() g2.join() g3.join()
运行结果当然在实际的代码里,我们不会用gevent.sleep()去切换协程,而是在执行到IO操作时gevent会自动完成,所以gevent需要将Python自带的一些标准库的运行方式由阻塞式调用变为协作式运行。这一过程在启动时通过monkey patch完成:
import timeimport geventfrom gevent import monkey# 猴子补丁,会自动将python的一些标准模块替换成gevent框架。慎用,它创造了“隐式的副作用”,如果出现问题 它很多时候是极难调试的。monkey.patch_all() # 注意:若导出的模块函数不会被替换,比如from time import sleep,sleep不会被替换def task(n): for i in range(n): print(gevent.getcurrent(), i) time.sleep(1) # 会被gevent自动替换为gevent.sleep()if __name__ == "__main__": g1 = gevent.spawn(task, 3) g2 = gevent.spawn(task, 3) g3 = gevent.spawn(task, 3) g1.join() g2.join() g3.join()
执行结果上面的流程看起来比较繁琐,可以使用 gevent.joinall() 方法简化流程:
import timeimport geventfrom gevent import monkey# 猴子补丁,会自动将python的一些标准模块替换成gevent框架。慎用,它创造了“隐式的副作用”,如果出现问题 它很多时候是极难调试的。monkey.patch_all() # 注意:若导出的模块函数不会被替换,比如from time import sleep,sleep不会被替换"""学习中遇到问题没人解答?小编创建了一个Python学习交流群:711312441寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!"""def task(n): for i in range(n): print(gevent.getcurrent(), i) time.sleep(1) # 会被gevent自动替换为gevent.sleep()if __name__ == "__main__": gevent.joinall([ gevent.spawn(task, 4), gevent.spawn(task, 4), gevent.spawn(task, 4), ])
执行结果
关键词:
Python多任务教程:进程、线程、协程
python中zeros函数和ones函数的详细用法
总投资约306亿元 南阳105个项目纳入2023年全省卫生健康“三个一批”项目
男子人肉占车位 雷克萨斯直接倒车撞 网友:解气但不提倡
49db智能降噪!iQOO TWS 1评测:戴上它 整个世界都安静了
被污名化太久!腾讯张立军:游戏强力推动芯片、AI等技术发展
2999元智商税“圾皇” 买完要被朋友嘲笑两年半
[初等数论]欧几里得算法:最大公因数/公因式求解算法的数学证明与程序实现
子/次模 (Submodular)、超模 (Supermodular)和模(Modular)函数
近期,四大生肖事业连走上坡路,收入节节高升,财运亨通
把充电速度带入“5G时代” 理想纯电车型搭载5C电池:不到十分钟续航400km
iPad mini唯一对手!新款联想拯救者Y700性能确认:搭载骁龙8+
李玟演唱《战歌》竟成绝唱 《斗罗大陆2》动画片头缅怀
都不买英伟达难受了:RTX 4080大降价 首次跌破1000美元!降到多少你会买?
我国新能源汽车达1620万辆 仅汽车保有量1/20 增长潜力巨大
苏州新建元控股集团董事长叶晓敏:未来REITs板块的表现依然值得期待
男生考上985研究生辞掉车企上万月薪工作:父母很支持
比亚迪汉同门兄弟!海豹DM-i要来了:20万级大杀四方
续航90公里 宝马发布全新电动摩托车CE 02:最高车速95km/h
潼关县两馆一中心预计今年12月建成
P1223 排队接水
打击乐器都有什么(打击乐器有哪些)
女子无人区遇乞食狼下车投喂 浑身瘦骨嶙峋感觉没危险:网友吐槽无知
夫妇中3亿7年后各自和新人住豪宅 网友唏嘘:果然有钱可以摧毁婚姻
上半年车市观察:几家欢喜几家愁,修炼内功迎“出海”
宝马隆重推出宝驴
杭州亚运会门票线上正式开售!购买教程出炉:官网、支付宝均可
联合国秘书长希望黑海港口农产品外运协议得以维持
中泰证券:7、8月企业排产已提升至积极 H2空调有望在低预期之下延续高增
炒菜给孕妇吃,能放什么调味料?
玉泉区昭君路街道开展“人人讲安全 个个会应急”安全生产月活动
德国5月工业产出意外下降 经济复苏前景再蒙阴霾
崇明这里,垃圾分类有了“新助手”
恒玄科技:上半年公司下游各个领域的客户需求都有所恢复
广东高考录取日程公布!7月16日开始本科批次录取
美国5月份贸易逆差达690亿美元 自俄进口商品服务月增1.3倍
茀莱堡口腔医院地址|南京种植牙价格表2023
英国房地产因利率上升陷入困境 房价正以2011年来最快速度下跌
群众转移、房屋清淤、重建选址……重庆强降雨后做了这些事
23深投02、22润置09、22润置12今日成交额位居交易所信用(非金)债券榜前三
这一天,我们不敢忘,也不能忘!
靠“抄作业”上市成功,曾经的“福建首富”,也难逃“退市”?
京源环保:7月6日公司高管季献华减持公司股份合计112.63万股
大连“科技创新+试点应用”打造普惠金融新体验
全国首列!徐州地铁3号线二期电客车亮相!
【全球市场晚报】7月7日
追光丨冬奥场馆的夏日玩法,你不想来吗?
满口种植牙多少钱[南京专业种植牙医院]茀莱堡口腔医院怎么样
文县临江镇欧家坝村灌溉渠道维修工程中标公示
一级造价师管理考试及答案一级造价工程师管理考试时间
阿斯巴甜致癌争议不休 健康减糖还能吃什么?
马斯克回应垄断火箭发射市场:SpaceX的使命是让生命多行星化
老鹰乐队告别演出
拒绝恶性竞争!比亚迪、特斯拉、蔚小理等约定不打价格战
富豪为对抗衰老上午11点后断食:曾跟17岁儿子换血 45岁拥有28岁的皮肤
Redmi Note 12 Pro宣布降价500元:8+128GB到手价1399元
40℃以上!郑州市继续发布高温红色预警信号
深圳市尚艺品工艺品有限公司销售不合格产品案
维科技术(600152):7月7日北向资金减持95.08万股
红警ol如何退出联盟 红警OL退出联盟方法
甘肃武威一公司广告词含“送领导”被罚2万?官方:属实
民科 关于民科介绍
宁夏评选出上半年10名“宁夏好人” 95后消防员因敬业奉献入选
水冷炉壁 关于水冷炉壁介绍
“不知香臭”竟是罕见病 南漳姐妹花喜迎“好孕”
金融助力农村新业态发展
最高人民检察院依法对付忠伟决定逮捕
忻州:通过竣工验收!
《逆水寒手游》废村探秘宝箱开启玩法
中指研究院发布《2023上半年中国房地产市场总结&下半年趋势展望》
商汤灭夏有证据吗 商汤灭夏的时间
通行能力怎么计算 通行能力
Win11关闭自动播放功能操作教程
华为的宏图是成为下一个十年最伟大的软件公司?
董事长周炜涉嫌行贿被留置细节披露,卫宁健康曾卷入医院行贿案
FDL发布2023年H1全球食品饮料趋势,解析4大创新机会点
新中式越来越流行,这样穿太高级了!
高中化学一轮考点最全总结,高考化学石油的考点,高考化学关于煤的题型
给力!206.7亿元,多个项目成功签约!
化敌为友!利马转发与芒特冲突照:现在我们是朋友了
中国配电箱行业现状与发展趋势及前景预测2023
利欧股份:部分董事及高管拟减持不超0.09%股份
金石滩纳帕总部基地正式开园
大学生毕业医疗保险怎么交?如何办理?
学生保险怎么查询是哪个公司的?有一些什么好处?
平安养老险贵州分公司开展“7.8保险 宣传日健步行”活动
已发"红包"近千亿!上半年基金分红很阔绰,这家公司最豪
寒武纪-U领跌超7%,科创芯片ETF华安(588290)震荡回调,连续2日吸金合计超3亿元
左边给骨斗罗画个龙,右边画一道彩虹,这才是骨化神龙该有的样子
离婚时共同债务应该怎么处理?
华为云盘古大模型3.0正式发布
联想昭阳k26内存更换视频(联想昭阳k26)
支持自动长文生成,WPS AI发布:基于大语言模型的智能办公助手
山西基本养老服务清单发布
永新光学属于ai眼镜概念股吗?(2023/7/7)
5000份“妈妈的手作”将进驻亚运村 巾帼志愿者吹响服务保障亚运盛会的冲锋号
从797元跌至80元,股价重挫89%,昔日千亿巨头失宠?
不服“违约纠纷案”一审判决 银座股份旗下公司提起上诉
全国城市网媒总编辑走进无限极,实地探访湾区“智”造
王铁成:王羲之赋