python總結(十七) 多執行緒

2021-09-24 20:41:11 字數 3640 閱讀 9580

1、由於任何程序預設就會啟動乙個執行緒,我們把該執行緒稱為主線程,主線程又可以啟動新的執行緒,python的threading模組有個current_thread()函式,它永遠返回當前執行緒的例項。主線程例項的名字叫mainthread,子執行緒的名字在建立時指定,我們用loopthread命名子執行緒。名字僅僅在列印時用來顯示,完全沒有其他意義,如果不起名字python就自動給執行緒命名為thread-1thread-2……多執行緒和多程序最大的不同在於,多程序中,同乙個變數,各自有乙份拷貝存在於每個程序中,互不影響,而多執行緒中,所有變數都由所有執行緒共享,所以,任何乙個變數都可以被任何乙個執行緒修改,因此,執行緒之間共享資料最大的危險在於多個執行緒同時改乙個變數,把內容給改亂了。

python的執行緒雖然是真正的執行緒,但直譯器執行**時,有乙個gil鎖:global interpreter lock,任何python執行緒執行前,必須先獲得gil鎖,然後,每執行100條位元組碼,直譯器就自動釋放gil鎖,讓別的執行緒有機會執行。這個gil全域性鎖實際上把所有執行緒的執行**都給上了鎖,所以,多執行緒在python中只能交替執行,即使100個執行緒跑在100核cpu上,也只能用到1個核。

gil是python直譯器設計的歷史遺留問題,通常我們用的直譯器是官方實現的cpython,要真正利用多核,除非重寫乙個不帶gil的直譯器。

所以,在python中,可以使用多執行緒,但不要指望能有效利用多核。如果一定要通過多執行緒利用多核,那只能通過c擴充套件來實現,不過這樣就失去了python簡單易用的特點。

import time

import threading

lock = threading.lock()

def matter1(music):

for i in range(0,len(music)):

print("第" + str(i + 1) + "首歌是:" + str(music[i]))

# 假設每一首歌曲的時間是2秒

time.sleep(1)

print("切換下一首歌..%s."% threading.current_thread().name)

def matter2(number):

lock.acquire()

j = 0

while j <= number:

print("我準備寫入第" + str(j + 1) +"行**")

j = j + 1

# 假設每寫一行**的時間為1秒

time.sleep(1)

print("寫下一行**%s..."% threading.current_thread().name)

lock.release()

def matter3(snacks):

lock.acquire()

for k in range(0,len(snacks)):

print("我正在聽著歌吃" + str(snacks[k]) + "零食")

#每吃一袋零食間隔5秒

time.sleep(1)

print("吃完了一包零食%s"% threading.current_thread().name)

lock.release()

def multi_thread():

begin = time.time()

args_list =

thread_list =

funcname = [matter1, matter2, matter3]

func_name = ["matter1","matter2","matter3"]

for fun in zip(func_name, funcname):

pro = threading.thread(target = fun[1], args=(args_list[fun[0]],), name="執行緒" + fun[0])

for t in thread_list:

t.setdaemon(true)

t.start()

for t in thread_list:

t.join()

end = time.time()

runtime = end - begin

print(runtime)

if __name__ == "__main__":

multi_thread()

2、對 threadlocal 的理解

是全域性變數,但是每個執行緒都有它的映象。

一、對 threadlocal 的理解

threadlocal,有的人叫它執行緒本地變數,也有的人叫它執行緒本地儲存,其實意思一樣。   threadlocal 在每乙個變數中都會建立乙個副本,每個執行緒都可以訪問自己內部的副本變數。

二、為什麼會出現 threadlocal 的技術應用

我們知道多執行緒環境下,每乙個執行緒均可以使用所屬程序的全域性變數。如果乙個執行緒對全域性變數進行了修改,將會影響到其他所有的執行緒對全域性變數的計算操作,從而出現資料混亂,即為髒資料。為了避免逗哥執行緒同時對變數進行修改,引入了執行緒同步機制,通過互斥鎖、條件變數或者讀寫鎖來控制對全域性變數的訪問。

只用全域性變數並不能滿足多執行緒環境的需求,很多時候執行緒還需要擁有自己的私有資料,這些資料對於其他執行緒來說是不可見的。因此執行緒中也可以使用區域性變數,區域性變數只有執行緒自身可以訪問,同乙個程序下的其他執行緒不可訪問。

有時候使用區域性變數不太方便,因此 python 還提供了threadlocal 變數,它本身是乙個全域性變數,但是每個執行緒卻可以利用它來儲存屬於自己的私有資料,這些私有資料對其他執行緒也是不可見的。

threadlocal 真正做到了執行緒之間的資料隔離。

import threading

# 建立全域性threadlocal物件:

local_school = threading.local()

def process_student():

# 獲取當前執行緒關聯的student:

std = local_school.student

print('hello, %s (in %s)' % (std, threading.current_thread().name))

def process_thread(name):

# 繫結threadlocal的student:

local_school.student = name

process_student()

t1 = threading.thread(target=process_thread, args=('alice',), name='thread-a')

t2 = threading.thread(target=process_thread, args=('bob',), name='thread-b')

t1.start()

t2.start()

t1.join()

t2.join()

threadlocal最常用的地方就是為每個執行緒繫結乙個資料庫連線,http請求,使用者身份資訊等,這樣乙個執行緒的所有呼叫到的處理函式都可以非常方便地訪問這些資源。

python多執行緒總結

1.定義幾個想在不同執行緒執行的函式 import threading from time import ctime,sleep defmusic a for i in range 2 print listen music s s a,ctime sleep 1 2.建立執行緒池 threads t...

python 多執行緒總結(一)

使用python已經有段時間了,一直想學一下多執行緒程式設計,一直被耽擱,這次好好學習一下,寫篇部落格,作為以後的參考,好記性不如爛筆頭,這句話的理解越來越深刻。參考 python 標準庫 來寫這篇文章的,有不足的地方,大家可以提出。python多執行緒有多種方法,這裡只是寫threading的方法...

Python 多執行緒庫總結

下面是一些基礎函式,函式包括 函式 threading.active count threading.current thread threading.get ident threading.enumerate threading.main thread threading.settrace fun...