真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Python多線程的實(shí)例分析

這篇文章給大家介紹Python多線程的實(shí)例分析,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

十年的梁子湖網(wǎng)站建設(shè)經(jīng)驗(yàn),針對設(shè)計(jì)、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。營銷型網(wǎng)站的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整梁子湖建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)公司從事“梁子湖網(wǎng)站設(shè)計(jì)”,“梁子湖網(wǎng)站推廣”以來,每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。

為什么有人會說 Python 多線程是雞肋?知乎上有人提出這樣一個(gè)問題,在我們常識中,多進(jìn)程、多線程都是通過并發(fā)的方式充分利用硬件資源提高程序的運(yùn)行效率,怎么在 Python 中反而成了雞肋?

有同學(xué)可能知道答案,因?yàn)?Python 中臭名昭著的 GIL。

那么 GIL 是什么?為什么會有 GIL?多線程真的是雞肋嗎? GIL 可以去掉嗎?帶著這些問題,我們一起往下看,同時(shí)需要你有一點(diǎn)點(diǎn)耐心。

多線程是不是雞肋,我們先做個(gè)實(shí)驗(yàn),實(shí)驗(yàn)非常簡單,就是將數(shù)字 “1億” 遞減,減到 0 程序就終止,這個(gè)任務(wù)如果我們使用單線程來執(zhí)行,完成時(shí)間會是多少?使用多線程又會是多少?show me the code

# 任務(wù)
def decrement(n):
   while n > 0:
       n -= 1

單線程

import time

start = time.time()
decrement(100000000)
cost = time.time() - start
>>> 6.541690826416016

在我的4核 CPU 計(jì)算機(jī)中,單線程所花的時(shí)間是 6.5 秒??赡苡腥藭枺€程在哪里?其實(shí)任何程序運(yùn)行時(shí),默認(rèn)都會有一個(gè)主線程在執(zhí)行。(關(guān)于線程與進(jìn)程這里不展開,我會單獨(dú)開一篇文章)

多線程

import threading

start = time.time()

t1 = threading.Thread(target=decrement, args=[50000000])
t2 = threading.Thread(target=decrement, args=[50000000])

t1.start() # 啟動線程,執(zhí)行任務(wù)
t2.start() # 同上

t1.join() # 主線程阻塞,直到t1執(zhí)行完成,主線程繼續(xù)往后執(zhí)行
t2.join() # 同上

cost = time.time() - start

>>>6.85541033744812

創(chuàng)建兩個(gè)子線程 t1、t2,每個(gè)線程各執(zhí)行 5 千萬次減操作,等兩個(gè)線程都執(zhí)行完后,主線程終止程序運(yùn)行。結(jié)果,兩個(gè)線程以合作的方式執(zhí)行是 6.8 秒,反而變慢了。按理來說,兩個(gè)線程同時(shí)并行地運(yùn)行在兩個(gè) CPU 之上,時(shí)間應(yīng)該減半才對,現(xiàn)在不減反增。

是什么原因?qū)е露嗑€程不快反慢的呢?

原因就在于 GIL ,在 Cpython 解釋器(Python語言的主流解釋器)中,有一把全局解釋鎖(Global Interpreter Lock),在解釋器解釋執(zhí)行 Python 代碼時(shí),先要得到這把鎖,意味著,任何時(shí)候只可能有一個(gè)線程在執(zhí)行代碼,其它線程要想獲得 CPU 執(zhí)行代碼指令,就必須先獲得這把鎖,如果鎖被其它線程占用了,那么該線程就只能等待,直到占有該鎖的線程釋放鎖才有執(zhí)行代碼指令的可能。

 

因此,這也就是為什么兩個(gè)線程一起執(zhí)行反而更加慢的原因,因?yàn)橥粫r(shí)刻,只有一個(gè)線程在運(yùn)行,其它線程只能等待,即使是多核CPU,也沒辦法讓多個(gè)線程「并行」地同時(shí)執(zhí)行代碼,只能是交替執(zhí)行,因?yàn)槎嗑€程涉及到上線文切換、鎖機(jī)制處理(獲取鎖,釋放鎖等),所以,多線程執(zhí)行不快反慢。

什么時(shí)候 GIL 被釋放呢?

當(dāng)一個(gè)線程遇到 I/O 任務(wù)時(shí),將釋放GIL。計(jì)算密集型(CPU-bound)線程執(zhí)行 100 次解釋器的計(jì)步(ticks)時(shí)(計(jì)步可粗略看作 Python 虛擬機(jī)的指令),也會釋放 GIL??梢酝ㄟ^ sys.setcheckinterval()設(shè)置計(jì)步長度,sys.getcheckinterval() 查看計(jì)步長度。相比單線程,這些多是多線程帶來的額外開銷

CPython 解釋器為什么要這樣設(shè)計(jì)?

多線程是為了適應(yīng)現(xiàn)代計(jì)算機(jī)硬件高速發(fā)展充分利用多核處理器的產(chǎn)物,通過多線程使得 CPU 資源可以被高效利用起來,Python 誕生于1991年,那時(shí)候硬件配置遠(yuǎn)沒有今天這樣豪華,現(xiàn)在一臺普通服務(wù)器32核64G內(nèi)存都不是什么司空見慣的事

但是多線程有個(gè)問題,怎么解決共享數(shù)據(jù)的同步、一致性問題,因?yàn)?,對于多個(gè)線程訪問共享數(shù)據(jù)時(shí),可能有兩個(gè)線程同時(shí)修改一個(gè)數(shù)據(jù)情況,如果沒有合適的機(jī)制保證數(shù)據(jù)的一致性,那么程序最終導(dǎo)致異常,所以,Python之父就搞了個(gè)全局的線程鎖,不管你數(shù)據(jù)有沒有同步問題,反正一刀切,上個(gè)全局鎖,保證數(shù)據(jù)安全。這也就是多線程雞肋的原因,因?yàn)樗鼪]有細(xì)粒度的控制數(shù)據(jù)的安全,而是用一種簡單粗暴的方式來解決。

這種解決辦法放在90年代,其實(shí)是沒什么問題的,畢竟,那時(shí)候的硬件配置還很簡陋,單核 CPU 還是主流,多線程的應(yīng)用場景也不多,大部分時(shí)候還是以單線程的方式運(yùn)行,單線程不要涉及線程的上下文切換,效率反而比多線程更高(在多核環(huán)境下,不適用此規(guī)則)。所以,采用 GIL 的方式來保證數(shù)據(jù)的一致性和安全,未必不可取,至少在當(dāng)時(shí)是一種成本很低的實(shí)現(xiàn)方式。

那么把 GIL 去掉可行嗎?

還真有人這么干多,但是結(jié)果令人失望,在1999年Greg Stein 和Mark Hammond 兩位哥們就創(chuàng)建了一個(gè)去掉 GIL 的 Python 分支,在所有可變數(shù)據(jù)結(jié)構(gòu)上把 GIL 替換為更為細(xì)粒度的鎖。然而,做過了基準(zhǔn)測試之后,去掉GIL的 Python 在單線程條件下執(zhí)行效率將近慢了2倍。

Python之父表示:基于以上的考慮,去掉GIL沒有太大的價(jià)值而不必花太多精力。

關(guān)于Python多線程的實(shí)例分析就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。


本文名稱:Python多線程的實(shí)例分析
網(wǎng)頁路徑:http://weahome.cn/article/picjpg.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部