电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

深入理解Python 多線程

瀏覽:88日期:2022-07-21 09:06:51

Python里的多線程是假的多線程,不管有多少核,同一時間只能在一個核中進行操作!利用Python的多線程,只是利用CPU上下文切換的優勢,看上去像是并發,其實只是個單線程,所以說他是假的單線程。

那么什么時候用多線程呢?

首先要知道:

io操作不占用CPU 計算操作占CPU,像2+5=5

Python的多線程不適合CPU密集操作型的任務,適合io密集操作型的任務,例如:SocketServer

如果現在再有CPU密集操作型的任務,那該怎么辦呢?

首先說,多進程的進程之間是獨立的,然后注意了,python的線程用的是系統的原生線程,python的進程也是用系統的原生進程,那原生進程是由操作系統維護的,說白了python只是利用C原生代碼庫的接口?E嚓起了個進程,真正的進程管理還是由操作系統來完成的,那么操作系統本身有GIL全局解釋器鎖嗎?答案是沒有的,且兩個進程之間的數據是完全獨立的,不能互相訪問,所以不需要鎖的概念,所以不存在GIL概念,所以在這種情況下,每個進程至少會有一個線程,如果現在我的操作系統是八核的,我起八個進程,然后每個進程里面都有一個線程,那么就相當于八線程了,八個線程跑在八核上,那么就相當于利用多核了,那么問題就解決了!

唯一的壞處是八個線程之間的數據是不能共享的,獨立的!利用這種方法可以折中的解決多核運算的問題!

先看一段簡單的多進程的程序:

import multiprocessingimport timedef run(name): time.sleep(2) print(’hello’, name)if __name__ == ’__main__’: for i in range(10): p = multiprocessing.Process(target=run, args=(’bob%s’%i,)) p.start()

程序的執行結果為:

hello bob0hello bob1hello bob3hello bob2hello bob5hello bob9hello bob7hello bob8hello bob4hello bob6

那么,如果我想取我的進程號,那該怎么取呢?

from multiprocessing import Processimport osdef info(title): print(title) print(’module name:’, __name__) print(’parent process:’, os.getppid()) # 父進程ID print(’process id:’, os.getpid()) # 自己進程的ID print('nn')def f(name): info(’033[31;1mfunction f033[0m’) print(’hello’, name)if __name__ == ’__main__’: info(’033[32;1mmain process line033[0m’) p = Process(target=f, args=(’bob’,)) p.start() p.join()

程序執行的結果為:

main process linemodule name: __main__parent process: 5252process id: 6576

function fmodule name: __mp_main__parent process: 6576process id: 2232

hello bob

深入理解Python 多線程

其實這幅圖片的意思是,每一個子進程都是由他父進程啟動的。

進程間通訊

我們說兩個進程之間的內存之間是相互獨立的,那么這兩個進程能夠進行通信嗎?說A進程向訪問B進程的數據,能訪問嗎?肯定是不可以訪問的!但是,我就是想訪問,也就是兩個獨立的內存想互相訪問,那該怎么辦呢?

有那么幾種方式,但是呢!萬變不離其宗,也即是說你必須找到一個中間件,有那么幾種中間件,那么先來看看是哪幾種

第一種Queues

使用方法跟threading里的queue差不多

from multiprocessing import Process, Queuedef f(q): q.put([42, None, ’hello’])if __name__ == ’__main__’: q = Queue() p = Process(target=f, args=(q,)) p.start() print(q.get()) # prints '[42, None, ’hello’]' p.join()

我們看這兩個進程,父進程的q是怎么傳給子進程的?我們來討論一下

現在我們是不是認為數據共享了,兩個進程共享了一個q,其實不是的,其實是相當于克隆了一個q,然后在父進程里創建個子進程,也就是父進程把自己的q克隆了一份交給了子進程,子進程這個時候往這個q里面放了一份數據,父進程能夠獲取到 。那么這么說就不對了,那克隆了一個q,也就是兩個q了,B往q里放了一個數據,那么與另一個q,也就是A的q也就沒關系了,噯,按說是這個樣子的,但是實際上呢,它是不是想實現個數據的共享啊,就相當于把A這個q里的數據序列化了,序列化到了一個中間的位置,而中間位置有一個翻譯,他把這個數據反序列化給A,放在了A的q里,那么也就是實現了所謂的數據共享了。

程序執行的結果為:

[42, None, ’hello’]

第二種Pipes

Pipe()函數返回一個由管道連接的連接對象,默認情況下是雙工(雙向)。 例如:

from multiprocessing import Process, Pipedef f(conn): conn.send('父親,安好?') # 兒子發 print('son receive:',conn.recv()) conn.close()if __name__ == ’__main__’: parent_conn, child_conn = Pipe() p = Process(target=f, args=(child_conn,)) p.start() print('father receive:',parent_conn.recv()) # 父親收 parent_conn.send('兒子,安好?') p.join()

程序執行后的結果為:

father receive: 父親,安好?son receive: 兒子,安好?

Pipe()返回的兩個連接對象代表管道的兩端。 每個連接對象都有send()和recv()方法(以及其他方法)。 請注意,如果兩個進程(或線程)同時嘗試讀取或寫入管道的同一端,則管道中的數據可能會損壞。 當然,同時使用管道的不同端部的過程不存在損壞的風險。

第三種Managers

Manager()返回的管理器對象控制一個服務器進程,該進程保存Python對象并允許其他進程使用代理操作它們。

Manager()返回的管理器將支持類型列表,dict,Namespace,Lock,RLock,Semaphore,BoundedSemaphore,Condition,Event,Barrier,Queue,Value和Array。 例如,

from multiprocessing import Process, Managerimport osdef f(d, l): d[1] = ’1’ d[’2’] = 2 d[0.25] = None l.append(os.getpid()) print(l)if __name__ == ’__main__’: with Manager() as manager: d = manager.dict() # 用專門的語法生成一個可在多個進程之間進行傳遞和共享的一個字典 l = manager.list(range(5)) # # 用專門的語法生成一個可在多個進程之間進行傳遞和共享的一個列表,默認里有5個數據 p_list = [] for i in range(10): p = Process(target=f, args=(d, l)) p.start() p_list.append(p) for res in p_list: res.join() print(d) print(l)

程序執行的結果為:

[0, 1, 2, 3, 4, 2100][0, 1, 2, 3, 4, 2100, 7632][0, 1, 2, 3, 4, 2100, 7632, 5788][0, 1, 2, 3, 4, 2100, 7632, 5788, 6340][0, 1, 2, 3, 4, 2100, 7632, 5788, 6340, 5760][0, 1, 2, 3, 4, 2100, 7632, 5788, 6340, 5760, 7072][0, 1, 2, 3, 4, 2100, 7632, 5788, 6340, 5760, 7072, 7540][0, 1, 2, 3, 4, 2100, 7632, 5788, 6340, 5760, 7072, 7540, 3904][0, 1, 2, 3, 4, 2100, 7632, 5788, 6340, 5760, 7072, 7540, 3904, 7888][0, 1, 2, 3, 4, 2100, 7632, 5788, 6340, 5760, 7072, 7540, 3904, 7888, 7612]{1: ’1’, ’2’: 2, 0.25: None}[0, 1, 2, 3, 4, 2100, 7632, 5788, 6340, 5760, 7072, 7540, 3904, 7888, 7612]

進程鎖與進程池

進程鎖

進程也有一個鎖,what?進程不都獨立了嗎?不涉及同時修改同一個數據,怎么還會有鎖呢?

閑了來看看它的表現形式,幾乎和線程是一模一樣的

from multiprocessing import Process, Lockdef f(l, i): l.acquire() try: print(’hello world’, i) finally: l.release()if __name__ == ’__main__’: lock = Lock() for num in range(10): Process(target=f, args=(lock, num)).start()

程序執行的結果為:

hello world 3hello world 1hello world 2hello world 5hello world 7hello world 4hello world 0hello world 6hello world 8hello world 9

那這種鎖有什么作用呢?

作用其實就是防止打印在屏幕上的信息發生錯亂現象!

進程池

在上面的程序中,啟動100個進程會發現變慢了,因為起一個進程就相當克隆了一份父進程的內存數據,如果父進程占一個G的內存空間,那我起100個進程,就相當于101G了,在這種情況下,開銷是非常大的,就像起一個進程?E嚓又克隆了一個屋子,一會就把哈爾濱占滿了,所以開銷特別大,為了避免?E嚓起那么多的進程,把系統打趴下,所以這里有個進程池的限制。

進程池就是同一時間有多少進程在CPU運行。

進程池中有兩個方法:

apply(同步執行,串行) apply_async(異步執行、并行)

from multiprocessing import Process,Pool,freeze_supportimport timeimport osdef Foo(i): time.sleep(2) print('in process',os.getpid()) return i+100def Bar(arg): print(’-->exec done:’,arg)if __name__ == ’__main__’: freeze_support() pool = Pool(5) # 允許進程池里同時放入5個進程 for i in range(10): # pool.apply_async(func=Foo, args=(i,),callback=Bar) # callback 回調 pool.apply(func=Foo, args=(i,)) # 串行 # pool.apply_async(func=Foo, args=(i,)) # 并行 print(’end’) pool.close() pool.join() # 進程池中進程執行完畢后再關閉,如果注釋,那么程序直接關閉。

程序的執行結果為:

in process 7824in process 6540in process 7724in process 8924in process 9108in process 7824in process 6540

知識點擴充:

__name__ == ’__main__’的作用是:

手動執行關于這段代碼的程序,那么他下面的程序就會執行,如果是調用這段代碼的程序時,那么它下面的程序就不會執行

以上就是深入理解Python 多線程的詳細內容,更多關于Python 多線程的資料請關注好吧啦網其它相關文章!

標簽: Python 編程
相關文章:
主站蜘蛛池模板: 阳光1号桔柚_无核沃柑_柑橘新品种枝条苗木批发 - 苧金网 | 专业深孔加工_东莞深孔钻加工_东莞深孔钻_东莞深孔加工_模具深孔钻加工厂-东莞市超耀实业有限公司 | 心肺复苏模拟人|医学模型|急救护理模型|医学教学模型上海康人医学仪器设备有限公司 | 全屋整木定制-橱柜,家具定制-四川峨眉山龙马木业有限公司 | 润东方环保空调,冷风机,厂房车间降温设备-20年深圳环保空调生产厂家 | 中细软知识产权_专业知识产权解决方案提供商 | 青岛侦探_青岛侦探事务所_青岛劝退小三_青岛婚外情取证-青岛王军侦探事务所 | 东风体检车厂家_公共卫生体检车_医院体检车_移动体检车-锦沅科贸 | 合肥活动房_安徽活动板房_集成打包箱房厂家-安徽玉强钢结构集成房屋有限公司 | 耐高温风管_耐高温软管_食品级软管_吸尘管_钢丝软管_卫生级软管_塑料波纹管-东莞市鑫翔宇软管有限公司 | 液压压力机,液压折弯机,液压剪板机,模锻液压机-鲁南新力机床有限公司 | 上海乾拓贸易有限公司-日本SMC电磁阀_德国FESTO电磁阀_德国FESTO气缸 | 回收二手冲床_金丰旧冲床回收_协易冲床回收 - 大鑫机械设备 | 变色龙PPT-国内原创PPT模板交易平台 - PPT贰零 - 西安聚讯网络科技有限公司 | 急救箱-应急箱-急救包厂家-北京红立方医疗设备有限公司 | 澳门精准正版免费大全,2025新澳门全年免费,新澳天天开奖免费资料大全最新,新澳2025今晚开奖资料,新澳马今天最快最新图库 | 挖掘机挖斗和铲斗生产厂家选择徐州崛起机械制造有限公司 | 欧盟ce检测认证_reach检测报告_第三方检测中心-深圳市威腾检验技术有限公司 | 细砂提取机,隔膜板框泥浆污泥压滤机,螺旋洗砂机设备,轮式洗砂机械,机制砂,圆锥颚式反击式破碎机,振动筛,滚筒筛,喂料机- 上海重睿环保设备有限公司 | OpenI 启智 新一代人工智能开源开放平台 | 河南卓美创业科技有限公司-河南卓美防雷公司-防雷接地-防雷工程-重庆避雷针-避雷器-防雷检测-避雷带-避雷针-避雷塔、机房防雷、古建筑防雷等-山西防雷公司 | RTO换向阀_VOC高温阀门_加热炉切断阀_双偏心软密封蝶阀_煤气蝶阀_提升阀-湖北霍科德阀门有限公司 | 粘度计NDJ-5S,粘度计NDJ-8S,越平水分测定仪-上海右一仪器有限公司 | 哈希PC1R1A,哈希CA9300,哈希SC4500-上海鑫嵩实业有限公司 | 牛皮纸|牛卡纸|进口牛皮纸|食品级牛皮纸|牛皮纸厂家-伽立实业 | 作文导航网_作文之家_满分作文_优秀作文_作文大全_作文素材_最新作文分享发布平台 | 宽带办理,电信宽带,移动宽带,联通宽带,电信宽带办理,移动宽带办理,联通宽带办理 | 钢格板_钢格栅_格栅板_钢格栅板 - 安平县鑫拓钢格栅板厂家 | 「安徽双凯」自动售货机-无人售货机-成人用品-自动饮料食品零食售货机 | 直线模组_滚珠丝杆滑台_模组滑台厂家_万里疆科技 | 北京网络营销推广_百度SEO搜索引擎优化公司_网站排名优化_谷歌SEO - 北京卓立海创信息技术有限公司 | 深圳离婚律师咨询「在线免费」华荣深圳婚姻律师事务所专办离婚纠纷案件 | 超声骨密度仪,双能X射线骨密度仪【起草单位】,骨密度检测仪厂家 - 品源医疗(江苏)有限公司 | 换网器_自动换网器_液压换网器--郑州海科熔体泵有限公司 | 鼓风干燥箱_真空烘箱_高温干燥箱_恒温培养箱-上海笃特科学仪器 | 重庆轻质隔墙板-重庆安吉升科技有限公司 | 船用锚链|专业锚链生产厂家|安徽亚太锚链制造有限公司 | 安徽华耐泵阀有限公司-官方网站 安德建奇火花机-阿奇夏米尔慢走丝|高维|发那科-北京杰森柏汇 | 丁基胶边来料加工,医用活塞边角料加工,异戊二烯橡胶边来料加工-河北盛唐橡胶制品有限公司 | 安徽净化工程设计_无尘净化车间工程_合肥净化实验室_安徽创世环境科技有限公司 | 点胶机_点胶阀_自动点胶机_智能点胶机_喷胶机_点胶机厂家【欧力克斯】 |