什么是線程?你為什么想要它?
Python是一種線性語言。但是砾淌,當(dāng)您需要更多的處理能力時篱瞎,線程模塊就派上用場了。
Python中的線程不能用于并行CPU計(jì)算达罗。但是它非常適合于I/O操作坝撑,比如web抓取静秆,因?yàn)樘幚砥魈幱诳臻e狀態(tài),等待數(shù)據(jù)巡李。
線程化改變了游戲規(guī)則抚笔,因?yàn)樵S多與網(wǎng)絡(luò)/數(shù)據(jù) I/O相關(guān)的腳本將大部分時間花費(fèi)在等待來自遠(yuǎn)程數(shù)據(jù)源上。有時候侨拦,下載可能沒有鏈接(例如殊橙,如果您正在抓取不同的網(wǎng)站),處理器可以并行地從不同的數(shù)據(jù)源下載并在最后合并結(jié)果狱从。
線程包含在標(biāo)準(zhǔn)庫中:
您可以使用target作為可調(diào)用的對象膨蛮,args將參數(shù)傳遞給函數(shù),并開始啟動線程:
鎖(lock)
您通常希望您的線程能夠使用或修改線程之間的公共變量季研。要做到這一點(diǎn)敞葛,你必須使用一種叫做鎖(lock)的東西。
每當(dāng)一個函數(shù)想要修改一個變量時与涡,它就會鎖定該變量惹谐。當(dāng)另一個函數(shù)想要使用一個變量時,它必須等待驼卖,直到該變量被解鎖氨肌。
假設(shè)有兩個函數(shù)都對一個變量進(jìn)行了1次迭代。鎖允許您確保一個函數(shù)可以訪問變量酌畜、執(zhí)行計(jì)算并在另一個函數(shù)訪問相同的變量之前寫回該變量怎囚。
您可以使用打印鎖來確保一次只能打印一個線程。這可以防止文本在打印時變得混亂(并導(dǎo)致數(shù)據(jù)損壞)桥胞。
在下面的代碼中桩了,我們有10個我們想要完成的工作和5個將要工作的工人:
Python作為一門不斷發(fā)展與普及的語言,還在不斷更新中埠戳。在學(xué)習(xí)時,建議找一些學(xué)習(xí)伙伴一起來學(xué)習(xí)和討論蕉扮,效果更佳整胃。如果想學(xué)習(xí)Python,歡迎加入Python學(xué)習(xí)交流群(627012464)喳钟,一起督促屁使,一起學(xué)習(xí)。里面有開發(fā)工具奔则,很多干貨和技術(shù)資料分享蛮寂!
多線程并不總是完美的解決方案
我們發(fā)現(xiàn)許多教程都傾向于忽略使用他們剛教過你的工具的缺點(diǎn)。理解使用所有這些工具的利弊是很重要的易茬。
例如:
1.管理線程需要時間酬蹋,因此它適用于基本任務(wù)(如示例)
2.線程化增加了程序的復(fù)雜性及老,從而增加了調(diào)試的難度
多進(jìn)程是什么?它與線程有什么不同?
在沒有多進(jìn)程(multiprocessing)的情況下,由于GIL(全局解釋器鎖 Global Interpreter Lock)范抓,Python程序很難最大化系統(tǒng)的規(guī)格骄恶。Python的設(shè)計(jì)并沒有考慮到個人計(jì)算機(jī)可能有多個核心。因此GIL是必要的匕垫,因?yàn)镻ython不是線程安全的僧鲁,而且在訪問Python對象時存在一個全局強(qiáng)制鎖。雖然不完美象泵,但它是一種非常有效的內(nèi)存管理機(jī)制寞秃。
多進(jìn)程允許您創(chuàng)建可以并發(fā)運(yùn)行的程序(繞過GIL)并使用整個CPU內(nèi)核。盡管它與線程庫有本質(zhì)的不同偶惠,但是語法非常相似春寿。多進(jìn)程庫為每個進(jìn)程提供了自己的Python解釋器,以及各自的GIL洲鸠。
因此堂淡,與線程相關(guān)的常見問題(如數(shù)據(jù)損壞和死鎖)不再是問題。因?yàn)檫M(jìn)程不共享內(nèi)存扒腕,所以它們不能并發(fā)地修改相同的內(nèi)存绢淀。
讓我們開始代碼演示:
如果您有一個共享數(shù)據(jù)庫,您希望確保在啟動新數(shù)據(jù)庫之前瘾腰,正在等待相關(guān)進(jìn)程完成皆的。
如果希望將參數(shù)傳遞給進(jìn)程,可以使用args實(shí)現(xiàn)這一點(diǎn):
這是一個簡單的例子蹋盆,因?yàn)檎缒⒁獾降姆驯。瑪?shù)字的排列順序與您所期望的不一致(沒有p.join())。
與線程一樣栖雾,多進(jìn)程仍然有缺點(diǎn)……你必須選擇其中一個壞處:
1.在進(jìn)程之間轉(zhuǎn)移數(shù)據(jù)會帶來I/O開銷
2.整個內(nèi)存被復(fù)制到每個子進(jìn)程中楞抡,對于更重要的程序來說,這會帶來很大的開銷
我們該用哪個
如果你的代碼有很多I/O或網(wǎng)絡(luò)使用:
多線程是您的最佳選擇析藕,因?yàn)樗拈_銷很低
如果你有一個圖形用戶界面
多線程是您的最佳選擇召廷,這樣你的UI線程就不會被鎖定
如果你的代碼是CPU限制:
您應(yīng)該使用多進(jìn)程(如果您的機(jī)器有多個核心)