Python多執行緒

2021-10-14 07:46:08 字數 4391 閱讀 1344

在對稱多處理器smp時代,python多執行緒技術顯得有些弱雞。因為gil的存在,python多執行緒只能實現單核多執行緒功能,無法實現多核多執行緒。雖然gil顯得有些自費武功,但是多執行緒技術在io密集型應用中仍然能夠提公升一部分系統效能。所以還是有必要學習一些python多執行緒程式設計。

在linux系統中,執行緒又名輕量級程序(lwp),是作業系統最小排程單位。這個命題,咋看起來沒問題,細細評味總覺得有點不準確,會給人產生一種錯覺,認為linux中最小排程單位是執行緒。

在linux2.6版本之後的版本,核心執行緒實現方式基本採用nptl。nptl是乙個1*1的執行緒庫,就是說當你使用pthread_create方法建立乙個執行緒後,在核心裡就相應建立了乙個排程實體,在linux裡就是乙個新程序,並且描述這個實體的資料結構仍然是task_struct。看到這裡,稍懂linux程序程式設計的人會得出這樣乙個結論:linux作業系統的排程單位從來沒變,仍然是以程序為單位。更詳細的執行緒介紹可以參考《深入理解linux核心》。

多執行緒程式設計

python多執行緒程式設計,離不開內建的threading庫。

1.繼承threading.thread類

import threading

​class testthread(threading.thread):

def __init__(self):

super(testthread,self).__init__() #必須呼叫父類

def run(self):

print self.name

2.使用函式呼叫方式

def pprint(log):

print log

​thread = threading.thread(target=pprint,args=('hello thread',))

thread.start()

3.設定守護執行緒

def pprint(log):

print log

​if __name__ == '__main__':

thread = threading.thread(target=pprint,args=('hello thread',))

thread.setdaemon(true)

thread.start()

守護執行緒的特點:主線程退出,守護執行緒也退出。

4.多執行緒共享全域性變數,使用互斥鎖對臨界區進行保護

import threading

import time

​count = 0

lock = threading.lock()

​def increment(name):

global count

with lock:

for i in range(3):

time.sleep(1)

print name

count += 1

​if __name__ == '__main__':

for i in range(10):

thread = threading.thread(target=increment,args=('thread-%s'%i,))

thread.start()

​ while true:

if threading.active_count() != 1:

continue

else:

break

print count

5.使用訊號量

import threading

import time

​def test(n,sem):

sem.acquire()

time.sleep(1)

print 'thread %s ' % n

sem.release()

​if __name__ == '__main__':

sem = threading.boundedsemaphore(4)

for i in range(10):

thread = threading.thread(target=test,args=(i,sem,))

thread.start()

​ while true:

if threading.active_count() != 1:

continue

else:

break

訊號量threading.boundedsemaphore允許不止乙個執行緒修改全域性變數,而互斥鎖任何時刻只允許乙個執行緒修改全域性變數。

6.事件

import threading

import time

​event = threading.event()

​def test(n):

event.set()

while true:

time.sleep(1)

print 'thread %s print hello event\n' % n

if event.is_set():

break

​if __name__ == '__main__':

sem = threading.boundedsemaphore(4)

for i in range(5):

thread = threading.thread(target=test,args=(i,))

thread.start()

time.sleep(5)

print 'main thread set event'

event.set()

事件可以用於乙個執行緒控制其它執行緒的執行。常用的方法有:set(設定flag為true),is_set(判斷是否設定了flag),clear(設定flag為false)和wait(監聽flag,如果沒有檢測到flag則阻塞當前執行緒)

7.定時器

import threading

import time

​def test():

time.sleep(1)

print 'hello timer'

​if __name__ == '__main__':

thread = threading.timer(1,test)

thread.start()

time.sleep(5)

print 'end'

定時器表示乙個操作需要在等待一定時間之後執行。定時器方法有4個引數:

8.柵欄(python3支援)

import threading

import time

​def test():

print('barrier')

​barrier = threading.barrier(3, test)​​

def barrier_thread(sleep):

time.sleep(sleep)

print('barrier thread-%s wait...' % sleep)

barrier.wait()

print('barrier thread-%s end!' % sleep)

​for i in range(6):

threading.thread(target=barrier_thread,args=(i,)).start()

輸出:

barrier thread-0 wait...

barrier thread-1 wait...

barrier thread-2 wait...

barrier

barrier thread-2 end!

barrier thread-0 end!

barrier thread-1 end!

barrier thread-3 wait...

barrier thread-4 wait...

barrier thread-5 wait...

barrier

barrier thread-5 end!

barrier thread-4 end!

barrier thread-3 end!

柵欄物件用於乙個固定數量的執行緒,而這些執行緒需要等待彼此的情況。這些執行緒中的每個執行緒都會嘗試呼叫wait()方法,然後阻塞,直到所有執行緒都呼叫了wait()方法,然後所有執行緒會被同時釋放。

小結在多核系統中,python多執行緒雖然只能利用單核,但是在io密集型應用中仍然有必要使用。

python多執行緒 python多執行緒

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

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

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

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

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