小編寫這篇文章的一個(gè)主要目的,主要是來給大家去做一個(gè)詳細(xì)解答,解答的內(nèi)容是對python多線程的一個(gè)相關(guān)理解,包括其對多核cpu利用的一個(gè)詳細(xì)解析,具體的內(nèi)容,請各位讀者仔細(xì)的進(jìn)行閱讀下文。
引言
我們經(jīng)常聽到"因?yàn)镚IL的存在,python的多線程不能利用多核CPU",現(xiàn)在我們暫且不提GIL,python能不能利用多核cpu,今天我做了一個(gè)實(shí)驗(yàn),代碼很簡單如下所示
while 1: pass
沒有運(yùn)行這段代碼前cpu狀態(tài)
運(yùn)行之后的狀態(tài)
下面兩張圖是運(yùn)行之后的狀態(tài),當(dāng)然這只是兩張比較有代表性的圖,截圖間隔有十幾秒的樣子
根據(jù)第一張圖我們發(fā)現(xiàn)cpu1、cpu3的負(fù)載有明顯增長,我們可以得出python線程是可以利用多核cpu的結(jié)論,之前一直以為python運(yùn)行后會綁定cpu其中的一個(gè)核心現(xiàn)在看來并不是這個(gè)樣子。第二張圖就比較有意思了cpu2滿載了,這又是為什么呢?
想來想去應(yīng)該是linux中cpu對進(jìn)程的親和性導(dǎo)致的,這種親和性是軟性的并不是強(qiáng)制的,這也就解釋了為什么第一張圖中是多cpu在負(fù)載。
ok為了更直觀的看出python線程能夠利用多核cpu,我們改下代碼,換一種方式再來看下
import os while 1: print os.getpid()#輸出進(jìn)程號
運(yùn)行代碼結(jié)果
一目了然,線程的確在不同的核心上切換。
現(xiàn)在我們回過頭看下那句經(jīng)典的話"因?yàn)镚IL的存在,python的多線程不能利用多核CPU",這句話很容易讓人理解成GIL會讓python在一個(gè)核心上運(yùn)行,有了今天的例子我們再來重新理解這句話,GIL的存在讓python在同一時(shí)刻只能有一個(gè)線程在運(yùn)行,這毋庸置疑,但是它并沒有給線程鎖死或者說指定只能在某個(gè)cpu上運(yùn)行,另外我需要說明一點(diǎn)的是GIL是與進(jìn)程對應(yīng)的,每個(gè)進(jìn)程都有一個(gè)GIL。
python線程的執(zhí)行流程理解
線程——>搶GIL——>CPU
這種執(zhí)行流程導(dǎo)致了CPU密集型的多線程程序雖然能夠利用多核cpu時(shí)跟單核cpu是差不多的,并且由于多個(gè)線程搶GIL這個(gè)環(huán)節(jié)導(dǎo)致運(yùn)行效率<=單線程。
看到這可能會讓人產(chǎn)生一種錯(cuò)覺,有了GIL后python是線程安全的,好像根本不需要線程鎖,而實(shí)際情況是線程拿到CPU資源后并不是一直執(zhí)行的,python解釋器在執(zhí)行了該線程100條字節(jié)碼(注意是字節(jié)碼不是代碼)時(shí)會釋放掉該線程的GIL,如果這時(shí)候沒有加鎖那么其他線程就可能修改該線程用到的資源;
遇到IO也會釋放GIL
另外一個(gè)問題是遇到IO也會釋放GIL,下面是這兩種情況的例子
import threading a=[] def m1(): for _ in range(100000): a.append(1) def m2(): for _ in range(100000): a.append(2) def check(): """ 檢查a是否有序 """ for i in range(len(a)): if i!=0: if a<i><a[i-1]: print a[i-1],a<i> return False return True t1=threading.Thread(target=m1) t2=threading.Thread(target=m2) t1.start() t2.start() t1.join() t2.join() print check() 預(yù)期1111...22222...,截圖顯示跟預(yù)期的不同 import threading text1='1'*10000 text2='2'*10000 def write(text): with open('test.txt','a')as f: f.write(text) def m1(): write(text1) def m2(): write(text2) t1=threading.Thread(target=m1) t2=threading.Thread(target=m2) t1.start() t2.start() t1.join() t2.join()
test.txt截圖
最后結(jié)論是,因?yàn)镚IL的存在,python的多線程雖然可以利用多核CPU,但并不能讓多個(gè)核同時(shí)工作。
綜上所述,上述內(nèi)容就給大家介紹完畢,希望可以給大家?guī)韼椭?/p>
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/128442.html
小編寫這篇文章的一個(gè)主要目的,主要是來給大家做個(gè)解答,解答的內(nèi)容主要是涉及到的內(nèi)容有Python解析器的一些相關(guān)介紹,介紹的內(nèi)容主要是Cpython的GIL解釋器解鎖相關(guān)機(jī)制的一些介紹。具體的內(nèi)容,下面就給大家詳細(xì)解答下。 本節(jié)重點(diǎn) 掌握Cpython的GIL解釋器鎖的工作機(jī)制 掌握GIL與互斥鎖 掌握Cpython下多線程與多進(jìn)程各自的應(yīng)用場景 本節(jié)時(shí)長需控制在45分鐘內(nèi) 一引子...
摘要:在一個(gè)進(jìn)程內(nèi)部,要同時(shí)干多件事,就需要同時(shí)運(yùn)行多個(gè)子任務(wù),我們把進(jìn)程內(nèi)的這些子任務(wù)稱為線程。總結(jié)一下,多任務(wù)的實(shí)現(xiàn)方式有三種多進(jìn)程模式多線程模式多進(jìn)程多線程模式線程是最小的執(zhí)行單元,而進(jìn)程由至少一個(gè)線程組成。 進(jìn)程與線程 很多同學(xué)都聽說過,現(xiàn)代操作系統(tǒng)比如Mac OS X,UNIX,Linux,Windows等,都是支持多任務(wù)的操作系統(tǒng)。 什么叫多任務(wù)呢?簡單地說,就是操作系統(tǒng)可以同時(shí)...
摘要:的解析器實(shí)現(xiàn)更成熟,第三方庫質(zhì)量高解析器盡管已經(jīng)有了很大的性能提升和很多新的功能,但是從源代碼實(shí)現(xiàn)的角度來說,基本上是通過在源代碼上打來增加功能的。相對而言,解析器更成熟,也比較穩(wěn)定。 最近在考慮學(xué)習(xí)一門后端語言,在ruby和python直接猶豫,然后自己做了一些對比,希望能幫到有同樣問題的你。 一、異同對比選擇1、Python和ruby的相同點(diǎn): 都強(qiáng)調(diào)語法簡單,都具有更一般的表達(dá)...
摘要:每個(gè)在同一時(shí)間只能執(zhí)行一個(gè)線程在單核下的多線程其實(shí)都只是并發(fā),不是并行,并發(fā)和并行從宏觀上來講都是同時(shí)處理多路請求的概念。在多線程下,每個(gè)線程的執(zhí)行方式獲取執(zhí)行代碼直到或者是虛擬機(jī)將其掛起。拿不到通行證的線程,就不允許進(jìn)入執(zhí)行。 進(jìn)程與線程 并發(fā)與并行 進(jìn)程與線程 首先要理解的是,我們的軟件都是運(yùn)行在操作系統(tǒng)之上,操作系統(tǒng)再控制硬件,比如 處理器、內(nèi)存、IO設(shè)備等。操作系統(tǒng)為了向上...
摘要:中單線程多線程與多進(jìn)程的效率對比實(shí)驗(yàn)多線程多進(jìn)程中多線程和多進(jìn)程的對比是運(yùn)行在解釋器中的語言,查找資料知道,中有一個(gè)全局鎖,在使用多進(jìn)程的情況下,不能發(fā)揮多核的優(yōu)勢。 title: Python中單線程、多線程與多進(jìn)程的效率對比實(shí)驗(yàn)date: 2016-09-30 07:05:47tags: [多線程,多進(jìn)程,Python]categories: [Python] meta: Pyt...
閱讀 917·2023-01-14 11:38
閱讀 888·2023-01-14 11:04
閱讀 747·2023-01-14 10:48
閱讀 2025·2023-01-14 10:34
閱讀 954·2023-01-14 10:24
閱讀 829·2023-01-14 10:18
閱讀 504·2023-01-14 10:09
閱讀 581·2023-01-14 10:02