在對稱多處理器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分鐘。多執行緒的情況下,程式就會同時進行多個任務,雖然在同一時刻也只能執行某個任...