每個程式執行一般會包含多個執行緒,對於python而言,它的多執行緒一般都是對於io密集型程式較為有效,因為其存在全域性直譯器鎖gil,所謂的全域性直譯器鎖,也就是只允許主迴圈中只有乙個執行緒在執行。但對於計算密集型的程式python的多執行緒就沒有什麼意義了。
全域性直譯器鎖的應用主要是為了保證資料安全,不出差錯。當多個執行緒同時對乙個資料訪問時,就會出錯。比如我們用50個執行緒向同乙個賬戶存入1塊錢時。當不使用鎖時。
import time
from threading import thread
defshow_time
(func)
:# 設定乙個修飾器
def(
*args,
**kwargs)
: start = time.time(
) func(
*args,
**kwargs)
end = time.time(
)print
(f'程式執行耗費時間'
)class
account()
:def
__init__
(self)
: self.all_money =
0 @property
defshow_money
(self)
:return self.all_money
defadd_money
(self, deposite_money)
: all_money = deposite_money + self.all_money # 此處重點 當你把此處改為self.all_money += deposite_money 是返回的資料其實還是安全的
#正是因為此處導致結果偏差,此時執行緒是不安全的
time.sleep(
0.01
) self.all_money = all_money
class
deposite_money
(thread)
:def
__init__
(self, acount, deposite_money)
:super()
.__init__(
) self.acount = acount
self.deposite_money = deposite_money
defrun(self)
: self.acount.add_money(self.deposite_money)
@show_time
defmain()
: threads =
my_acount = account(
)for i in
range(50
):a = deposite_money(my_acount,1)
a.start(
)for thread in threads:
thread.join(
)print
(f'賬戶餘額總數為'
)if __name__ ==
'__main__'
: main(
)
以下的**是使用鎖之後的
from threading import thread, lock
import time
defshow_time
(func)
:# 建立乙個修飾器顯示程式執行時間
def(
*args,
**kwargs)
: start = time.time(
) func(
*args,
**kwargs)
end = time.time(
)print
(f'程式執行耗費秒'
)
class
account()
:"""
加鎖類"""
def__init__
(self)
: self.all_money =
0 self.lock = lock(
) @property
# 修飾器 保護all_money資料,對外只顯示show_money介面
defshow_money
(self)
:return self.all_money
defadd_money
(self, deposite_money)
:# 此時的deposite_money沒有初始化,需要外部匯入
self.lock.acquire(
)# 加上執行緒鎖
try:
self.all_money += deposite_money
time.sleep(
0.05
)finally
: self.lock.release(
)# 解鎖
class
deposit_money
(thread)
:"""
建立乙個執行緒類
先是初始化__init__()
接著使用run()完成相關操作
"""def__init__
(self, acount, deposite_money)
:super()
.__init__(
) self.acount = acount # 直接匯入乙個類的例項
self.deposite_money = deposite_money
defrun(self)
: self.acount.add_money(self.deposite_money)
@show_time
defmain()
: threads =
my_count = account(
)for thread in
range(50
):# 用for迴圈建立50個執行緒
a = deposit_money(my_count,1)
a.start(
)for thread in threads:
thread.join(
)# 阻塞直到全部執行緒執行結束
print
(f'賬戶餘款總數為:'
)if __name__ ==
'__main__'
: main(
)
除了存錢的例子外,還有比如我使用乙個執行緒對乙個列表進行賦值,同一時間用另乙個執行緒對同乙個列表進行列印print()此時就會發現列印出來的可能就只是半個剛剛賦值的列表,這種情況也是衝突的。
對於函式的一些零散的應用,如map()和reduce()內建函式,map()函式有兩個引數,第乙個是函式,第二個一般是列表,返回的結果是對應值在函式中作用的結果。比如
def
multi
(x):
return x**
2map
(multi,[1
,3,4
,5])
print
(list
(map
(multi,[1
,3,4
,5])
)# 結果會是 1, 9, 16, 25
map(
int,
input()
.split())
#乙個個整數
而reduce中也是兩個引數,乙個函式,乙個常為列表,但這個函式要兩個引數,返回的結果為f(f(f(x1, x2), x3), x4)型別。
還有就是lambdas 的使用,comp = lambads x,y: x在這吐槽一下那個不知怎麼就熱起來的秋天的第一杯奶茶,對我來說秋天的第一杯奶茶是是高攀不起了,但是再等等,我應該可以吃到冬天的第一口西北風。
python多執行緒 python多執行緒
通常來說,多程序適用於計算密集型任務,多執行緒適用於io密集型任務,如網路爬蟲。關於多執行緒和多程序的區別,請參考這個 下面將使用python標準庫的multiprocessing包來嘗試多執行緒的操作,在python中呼叫多執行緒要使用multiprocessing.dummy,如果是多程序則去掉...
python多執行緒詳解 Python多執行緒詳解
前言 由於最近的工作中一直需要用到python去處理資料,而在面對大量的資料時,python多執行緒的優勢就展現出來了。因而藉此機會,盡可能詳盡地來闡述python多執行緒。但對於其更底層的實現機制,在此不做深究,僅是對於之前的一知半解做個補充,也希望初學者能夠通過這篇文章,即便是照葫蘆畫瓢,也能夠...
python程式多執行緒 PYTHON多執行緒
在單執行緒的情況下,程式是逐條指令順序執行的。同一時間只做乙個任務,完成了乙個任務再進行下乙個任務。比如有5個人吃飯,單執行緒一次只允許乙個人吃,乙個人吃完了另乙個人才能接著吃,假如每個人吃飯都需要1分鐘,5個人就需要5分鐘。多執行緒的情況下,程式就會同時進行多個任務,雖然在同一時刻也只能執行某個任...