理解 Python 中的多執行緒

2022-09-08 02:24:12 字數 4276 閱讀 6225

1、單執行緒

import

time

import

urllib2

defget_responses():

urls =[

'','',

'','',

'']start =time.time()

for url in

urls:

print

url resp =urllib2.urlopen(url)

print

resp.getcode()

print

"elapsed time: %s

" % (time.time()-start)

get_responses()

解釋:url順序的被請求 

除非cpu從乙個url獲得了回應,否則不會去請求下乙個url 

網路請求會花費較長的時間,所以cpu在等待網路請求的返回時間內一直處於閒置狀態。

2、多執行緒

import

urllib2

import

time

from threading import

thread

class

geturlthread(thread):

def__init__

(self, url):

self.url =url

super(geturlthread, self).

__init__()

defrun(self):

resp =urllib2.urlopen(self.url)

print

self.url, resp.getcode()

defget_responses():

urls =[

'',

'',

'',

'',

'']start =time.time()

threads =

for url in

urls:

t =geturlthread(url)

t.start()

for t in

threads:

t.join()

print

"elapsed time: %s

" % (time.time()-start)

get_responses()

解釋: 

意識到了程式在執行時間上的提公升 

我們寫了乙個多執行緒程式來減少cpu的等待時間,當我們在等待乙個執行緒內的網路請求返回時,這時cpu可以切換到其他執行緒去進行其他執行緒內的網路請求。 

我們期望乙個執行緒處理乙個url,所以例項化執行緒類的時候我們傳了乙個url。 

執行緒執行意味著執行類裡的run()方法。 

無論如何我們想每個執行緒必須執行run()。 

為每個url建立乙個執行緒並且呼叫start()方法,這告訴了cpu可以執行執行緒中的run()方法了。 

我們希望所有的執行緒執行完畢的時候再計算花費的時間,所以呼叫了join()方法。 

join()可以通知主線程等待這個執行緒結束後,才可以執行下一條指令。 

每個執行緒我們都呼叫了join()方法,所以我們是在所有執行緒執行完畢後計算的執行時間。 

關於執行緒: 

cpu可能不會在呼叫start()後馬上執行run()方法。 

你不能確定run()在不同執行緒建間的執行順序。 

對於單獨的乙個執行緒,可以保證run()方法裡的語句是按照順序執行的。 

這就是因為執行緒內的url會首先被請求,然後列印出返回的結果。

解決資源競爭

from threading import

lock, thread

lock =lock()

some_var =0

class

incrementthread(thread):

defrun(self):

#we want to read a global variable

#and then increment it

global

some_var

lock.acquire()

read_value =some_var

print

"some_var in %s is %d

" %(self.name, read_value)

some_var = read_value + 1

print

"some_var in %s after increment is %d

" %(self.name, some_var)

lock.release()

defuse_increment_thread():

threads =

for i in range(50):

t =incrementthread()

t.start()

for t in

threads:

t.join()

print

"after 50 modifications, some_var should h**e become 50

"print

"after 50 modifications, some_var is %d

" %(some_var,)

use_increment_thread()

解釋: 

lock 用來防止競爭條件 

如果在執行一些操作之前,執行緒t1獲得了鎖。其他的執行緒在t1釋放lock之前,不會執行相同的操作 

我們想要確定的是一旦執行緒t1已經讀取了some_var,直到t1完成了修改some_var,其他的執行緒才可以讀取some_var 

這樣讀取和修改some_var成了邏輯上的原子操作

加鎖保證操作的原子性

from threading import

thread, lock

import

time

lock =lock()

class

createlistthread(thread):

defrun(self):

self.entries =

for i in range(10):

time.sleep(0.01)

lock.acquire()

print

self.entries

lock.release()

defuse_create_list_thread():

for i in range(3):

t =createlistthread()

t.start()

use_create_list_thread()

證明了乙個執行緒不可以修改其他執行緒內部的變數(非全域性變數)。

import

threadpool

import

time

import

urllib2

urls =[

'',

'',

'',

'',

'']defmyrequest(url):

resp =urllib2.urlopen(url)

print

url, resp.getcode()

deftimecost(request, n):

print

"elapsed time: %s

" % (time.time()-start)

start =time.time()

pool = threadpool.threadpool(5)

reqs =threadpool.makerequests(myrequest, urls, timecost)

[ pool.putrequest(req)

for req in

reqs ]

pool.wait()

makerequests建立了要開啟多執行緒的函式,以及函式相關引數和**函式,其中**函式可以不寫,default是無,也就是說makerequests只需要2個引數就可以執行;

注意:threadpool 是非執行緒安全的。

python中多執行緒 Python之多執行緒

python之多執行緒 一 概念 1 多工可以由多程序完成,也可以由乙個程序內的多執行緒完成。程序是由若干的執行緒組成,乙個程序至少有乙個程序。執行緒是作業系統直接支援的執行單元,天賜高階預壓通常都是內建多執行緒的支援,python的執行緒是真正的posix thread而不是模擬出來的執行緒。2 ...

python中的多執行緒

python中的多執行緒是假的多執行緒!為什麼這麼說,我們先明確乙個概念,全域性直譯器鎖 gil global interpreter lock python 的執行由python虛擬機器 直譯器 來控制,同時只有乙個執行緒在執行 對python虛擬機器的訪問由全域性直譯器鎖 gil 來控制,正是這...

python中的多執行緒

當python程式執行時會預設建立乙個主線程,除了主線程之外我們還可以建立別的執行緒,可以使用threading引入 import threading import time defthinking for i in range 3 threading.current thread 檢視當前正在執行...