Python程序與執行緒及GIL(全域性直譯器鎖)

2021-10-10 02:32:04 字數 4169 閱讀 4501

程式並不能單獨執行,只有將程式裝載到記憶體中,系統為它分配資源才能執行,

而這種乙個程式在乙個資料集上的一次動態執行過程就稱之為程序。

程式和程序的區別就在於:程式是指令的集合,它是程序執行的靜態描述文字;

程序是程式的一次執行活動,屬於動態概念。程序一般由程式、資料集、程序控制塊三部分組成。

有了程序為什麼還要有執行緒呢?

因為程序還是有缺陷的:

程序只能在乙個時間幹一件事,如果想同時幹兩件事或多件事,程序就無能為力了

程序在執行的過程中如果阻塞,例如等待輸入,整個程序就會掛起,即使程序中有些工作不依賴於輸入的資料,也將無法執行

那麼什麼是執行緒呢?
執行緒是作業系統能夠進行運算排程的最小單位。它被包含在程序之中,是程序中的實際運作單位。

一條執行緒指的是程序中乙個單一順序的控制流,乙個程序中可以併發多個執行緒,每條執行緒並行執行不同的任務

程序和執行緒的關係:
1. 乙個執行緒只能屬於乙個程序,而乙個程序可以有多個執行緒,但至少有乙個執行緒。 

2. 資源分配給程序,同一程序的所有執行緒共享該程序的所有資源。

3. cpu分給執行緒,即真正在cpu上執行的是執行緒。

4. 程序:資源管理單位 (容器),執行緒:最小執行單位

並行和併發

並行處理的主要目的是節省大型和複雜問題的解決時間。

併發處理:指乙個時間段中有幾個程式都處於已啟動執行到執行完畢之間,且這幾個程式都是在同乙個處理機(cpu)上執行,

但任乙個時刻點上只有乙個程式在處理機(cpu)上執行

同步與非同步

同步:指乙個程序在執行某個請求的時候,若該請求需要一段時間才能返回資訊,那麼這個程序將會一直等待下去,

直到收到返回資訊才繼續執行下去。

非同步:指程序不需要一直等待下去,而是繼續執行下面的操作,不管其他程序的狀態,當有訊息返回時系統會通知

程序進行處理,這樣可以提高執行效率

python中的執行緒是作業系統的原生執行緒,python虛擬機器使用乙個全域性直譯器鎖(global interpreter lock)

來互斥執行緒對python虛擬機器的使用。為了支援多執行緒機制,乙個基本的要求就是需要實現不同執行緒對共享資源訪問的互斥,

所以引入了gil。

在呼叫任何python c api之前,要先獲得gil

gil缺點:多處理器退化為單處理器;

優點:避免大量的加鎖解鎖操作

python的多執行緒:由於gil鎖,導致同一時刻,同一程序只能有乙個執行緒被執行

總結:

對於計算密集型任務(一直在使用cpu):python的多執行緒並沒有用

對於io密集型任務(存在大量io操作):python的多執行緒是有意義的

要想使python使用多核:只能開程序, 弊端:開銷大而且切換複雜

使用多核的著重點應該放在:協程+多程序

終極思路:換c模組實現多執行緒

threading模組
import threading

import time

defcountnum

(n):

# 定義某個執行緒要執行的函式

print

("running on number:%s"

%n) time.sleep(3)

if __name__ ==

'__main__'

: t1 = threading.thread(target=countnum,args=(23

,))#生成乙個執行緒例項

t2 = threading.thread(target=countnum,args=(34

,)) t1.start(

)#啟動執行緒

t2.start(

)print

("ending!"

)

繼承thread式建立:
import threading

import time

class

mythread

(threading.thread)

:def

__init__

(self,num)

: threading.thread.__init__(self)

self.num=num

defrun(self)

:print

("running on number:%s"

%self.num)

time.sleep(3)

t1=mythread(56)

t2=mythread(78)

t1.start(

)t2.start(

)print

("ending"

)

join()方法和setdaemon()方法
# join():在子執行緒完成執行之前,這個子執行緒的父執行緒將一直被阻塞。

# setdaemon(true):

''' 將執行緒宣告為守護執行緒,必須在start() 方法呼叫之前設定,如果不設定為守護執行緒程式會被無限掛起。

當我們在程式執行中,執行乙個主線程,如果主線程又建立乙個子執行緒,主線程和子執行緒 就分兵兩路,分別執行,那麼當主線程完成

想退出時,會檢驗子執行緒是否完成。如果子執行緒未完成,則主線程會等待子執行緒完成後再退出。但是有時候我們需要的是只要主線程

完成了,不管子執行緒是否完成,都要和主線程一起退出,這時就可以 用setdaemon方法啦

'''import threading

from time import ctime,sleep

import time

defmusic

(name)

:print

("begin listening to . "

.format

(name=name,time=ctime())

) sleep(3)

print

("end listening "

.format

(time=ctime())

)def

blog

(title)

:print

("begin recording the . "

.format

(title=title,time=ctime())

) sleep(5)

print

('end recording '

.format

(time=ctime())

)threads =

t1 = threading.thread(target=music,args=

('fill me',)

)t2 = threading.thread(target=blog,args=(''

,))if __name__ ==

'__main__'

:#t2.setdaemon(true)

for t in threads:

#t.setdaemon(true) #注意:一定在start之前設定

t.start(

)#t.join()

#t1.join()

#t2.join() # 考慮這三種join位置下的結果?

print

("all over %s"

%ctime(

))

其他方法:
thread例項物件的方法

# isalive(): 返回執行緒是否活動的。

# getname(): 返回執行緒名。

# setname(): 設定執行緒名。

threading模組提供的一些方法:

# threading.currentthread(): 返回當前的執行緒變數。

# threading.enumerate(): 返回乙個包含正在執行的執行緒的list。正在執行指執行緒啟動後、結束前,不包括啟動前和終止後的執行緒。

# threading.activecount(): 返回正在執行的執行緒數量,與len(threading.enumerate())有相同的結果。

程序 執行緒 python的GIL

由於計算機資源有限,程式競爭計算機資源 程序 競爭計算機資源的基本單位,至少有乙個程序 單核cpu只能執行乙個程式?在不同的應用程式程序之間切換 多核 4核8核 程序排程演算法 乙個程式被掛起切換到另乙個程式 程序 執行緒 切換開銷使非常大的 cpu利用率降低,一些cpu的資源消耗到程序切換中 執行...

Python多執行緒與GIL

gil global interpreter lock 是在實現python解析器 cpython 時所引入的乙個概念。但值得注意的是,gil並不一定是所有python編譯器均必須的,如jpython就沒有gil。gil是python為解決多執行緒之間資料完整性和狀態同步的辦法,類似於在存在乙個全域...

執行緒,執行緒安全與python的GIL鎖

今天看到一篇文章,講述的是幾個提公升python效能的專案 傳送門 在看的過程中,接觸到乙個名詞,乙個從學python開始就一直看到,但是從來都是一知半解的名詞,心裡不開心,必須把它搞明白,對了,這個詞就是 gil。網上搜尋了一些資料,粗淺的理解了什麼是gil,自己感覺學習的過程比較好,感覺略有收穫...