python多執行緒

2021-07-17 04:56:42 字數 4179 閱讀 3440

**

執行緒(英語:thread)是作業系統能夠進行運算排程的最小單位。它被包含在程序之中,是程序中的實際運作單位。一條執行緒指的是程序中乙個單一順序的控制流,乙個程序中可以併發多個執行緒,每條執行緒並行執行不同的任務。(維基百科)

上面的解釋很抽象吧,我再解釋一下。當乙個程式啟動時,就會產生乙個程序或者多個程序,當乙個程序產生,同時也會產生乙個程序,這個程序就是主程序。而主程序還會產生子程序,這些子程序是可以同時進行的。

例如,有兩個這樣的程式:

def

a():

print('第乙個函式')

defb

(): print('第二個函式')

a()b()

上面的程式先執行函式a(),再執行函式b()。如果要用到程序的話,函式a()和函式b()可以同時進行。

** python提供了threading模組進行程序的調控。我們把上面的那段程式改寫成多程序的:

import threading

defa

(): print('第乙個函式\n')

defb

(): print('第二個函式\n')

th1=threading.thread(target=a)

th2=threading.thread(target=b)

th1.start()

th2.start()

執行結果:

>>> 第乙個函式

第二個函式

也有可能是:

>>> 第二個函式

第乙個函式

為什麼會出現這種狀況,為什麼呢?因為函式a()和函式b()是同時啟動的,執行時間差不多,所以有可能是a()先執行完,也有可能是b()先執行完。然後,我們再看看程序的形式th1=threading.thread(target=a),其中th1是子程序的名字,target鎖定函式,如果函式有引數怎麼辦?要寫成threading.thread(target=a,args=(x,x))這種形式。當把函式寫程序式後,就要啟動,th1.start()

這段程式不太能體現出線程的優點,我們再寫一段程式:

import threading,time

defa

(): print('a begin!')

print('a is running.........')

time.sleep(2)

print('a end!')

defb

(): print('b begin!')

print('b is running.........')

time.sleep(2)

print('b end!')

_time=time.time()

a()b()

print('共耗時%f秒'%(time.time()-_time))

執行結果:

a begin!

a is running.........

aend!

b begin!

b is running.........

b end!

共耗時4.058232秒

上面的**沒有寫成程序,所以共耗時4秒。我們把它寫成程序:

import threading,time

defa

(): print('a begin!')

print('a is running.........')

time.sleep(2)

print('a end!')

defb

(): print('b begin!')

print('b is running.........')

time.sleep(2)

print('b end!')

_time=time.time()

_a=threading.thread(target=a)

_b=threading.thread(target=b)

_a.start()

_b.start()

_b.join()

_b.join()

print('共耗時%f秒'%(time.time()-_time))

執行結果:

a begin!b begin!

a is running.........b is running.........

a end!b end!

共耗時2.073119秒

從上面的結果可以看出耗時2秒,節省了一半時間。join()函式是起到阻塞的作用,詳細用法見我的部落格:python多執行緒中join和setdaemon的用法。

** 先寫個例項程式:

import threading,time

num=0

defa

(n):

global num

num=num+n

num=num-n

defchange

(n):

for i in range(100000):

a(n)

t1=threading.thread(target=change,args=(5,))

t2=threading.thread(target=change,args=(8,))

t1.start()

t2.start()

t1.join()

t2.join()

print(num)

在上面**中,執行函式change(),根據我們的演算法,無論函式的引數是多少,執行多少次,num的結果應該始終是零。但是執行結果如下:

13
或者:

-2
這是為什麼呢?num是全域性變數,在同一程序下的執行緒之間的變數是共享的,所以,在t1和t2這兩個程序中都會對num進行操作。當執行到執行緒t1中num=num+你,應該接著執行t1程序中的num=num-1,但是程序都是同時進行的,所以會對num進行執行緒t2中的操作,num因此會出現其他值。為了避免多個程序同時對乙個變數或者檔案操作,python引進了互斥鎖:當乙個程序對乙個變數或乙個檔案進行操作時,會禁止其他程序對此變數或者檔案進行操作。我們可以將上面的**改寫如下:

import threading,time

num=0

mylock=threading.lock()

defa

(n):

global num

mylock.acquire()

num=num+n

num=num-n

mylock.release()

defchange

(n):

for i in range(100000):

a(n)

t1=threading.thread(target=change,args=(5,))

t2=threading.thread(target=change,args=(8,))

t1.start()

t2.start()

t1.join()

t2.join()

print(num)

這樣執行的結果始終是0。此外,只要加鎖就一定要解鎖,否則會形成死鎖,就是其他程序始終不能對變數進行操作。加鎖的位置只要能夠將變數包住就行,例如將鎖加在如下位置也可以:

def

change

(n):

for i in range(100000):

mylock.acquire()

a(n)

mylock.release()

**

在python中的多執行緒其實並不能真正利用多核cpu的優勢,這是因為在python中有乙個gil(global interpreter lock)。python在執行多執行緒程式時,其中乙個執行緒在執行前先獲gil,這樣其他的執行緒就不能執行。當第乙個執行緒執行了若干行**後再釋放gil,由另外乙個執行緒獲得gil並執行。由此可見,早python中多執行緒必不能有效的利用多核cpu的優勢。因此為了個好的有效利用多核cpu,所以我們可以建立多個多執行緒的程序。

python多執行緒 python多執行緒

通常來說,多程序適用於計算密集型任務,多執行緒適用於io密集型任務,如網路爬蟲。關於多執行緒和多程序的區別,請參考這個 下面將使用python標準庫的multiprocessing包來嘗試多執行緒的操作,在python中呼叫多執行緒要使用multiprocessing.dummy,如果是多程序則去掉...

python多執行緒詳解 Python多執行緒詳解

前言 由於最近的工作中一直需要用到python去處理資料,而在面對大量的資料時,python多執行緒的優勢就展現出來了。因而藉此機會,盡可能詳盡地來闡述python多執行緒。但對於其更底層的實現機制,在此不做深究,僅是對於之前的一知半解做個補充,也希望初學者能夠通過這篇文章,即便是照葫蘆畫瓢,也能夠...

python程式多執行緒 PYTHON多執行緒

在單執行緒的情況下,程式是逐條指令順序執行的。同一時間只做乙個任務,完成了乙個任務再進行下乙個任務。比如有5個人吃飯,單執行緒一次只允許乙個人吃,乙個人吃完了另乙個人才能接著吃,假如每個人吃飯都需要1分鐘,5個人就需要5分鐘。多執行緒的情況下,程式就會同時進行多個任務,雖然在同一時刻也只能執行某個任...