執行緒,共享資源,鎖
阿新 • • 發佈:2018-11-29
執行緒的概念
程序的概念:執行著的程式
每個程序裡面至少有一個執行緒
執行緒是作業系統建立的,用力啊控制程式碼執行的資料結構
執行緒就像程式碼的執行許可證
單執行緒程式。主執行緒的入口就是程式碼的開頭
主執行緒順序往下執行,直到所有的程式碼都執行完
**
概念對應(銀行裡面辦理業務)
**
一個服務視窗 = CPU的一個核
客戶 = 程序(執行著的程式)
排程員 = 作業系統(OS)
服務號 = 執行緒
排程員分配服務號給客戶 = OS分配執行緒給程序程式碼
服務視窗給客戶辦理業務 = CPU核心執行執行緒程式碼
排程的概念
排程員分配視窗給客戶 一個客戶不一定佔用一個視窗直到它結束 比如需要很長時間填寫表格 這是可以讓下一個客戶辦理 先前的客戶填好了表格,在繼續 作業系統不會讓一個執行緒一直佔用CPU的
程序裡的多執行緒
執行緒庫
程式碼通過系統呼叫,請求os分配一個新的執行緒
python裡面使用封裝好的庫,python3只有threading,是標準庫裡面的
thread
threading
都可以用來建立和管理執行緒
thread比較底層
threading是thread模組的擴充套件,提供了很多執行緒同步功能,使用起來更加方便強大
例子:
print("main thread start.") import threading from time import sleep def thread1_entry(): print("child thread 1,start") sleep(15) print("child thread 1,end") t1 = threading.Thread(target=thread1_entry) #Thread是一個類Thread()是例項化一個類,傳入初始化方法的引數,target傳的是這個函式的名字,不是呼叫。不加括號是函式的物件。 t1.start() #t1是Thread的例項物件,從這個點開始就啟動了一個新的執行緒 sleep(10) #主執行緒要sleep10秒 主執行緒先結束 print("main thread end.")
#結果
main thread start.
child thread 1,start
main thread end.
child thread 1,end
有些場景是:主執行緒要等待子執行緒執行完,比如子執行緒爬去資料,主執行緒分析資料、
要等到子執行緒結束(執行緒的.join()方法)
import threading from time import sleep,ctime,time def thread1_entry(nsec): print("child thread 1,start at:",ctime()) sleep(nsec) print("child thread 1,end at:",ctime()) def thread2_entry(nsec): print("child thread 2,start at:",ctime()) sleep(nsec) print("child thread 2,end at:",ctime()) print("main thread start.") #建立執行緒物件,指定了新執行緒的入口函式,args是傳入入口函式的引數 t1 = threading.Thread(target=thread1_entry,args=(1,)) #Thread是一個類Thread()是例項化一個類,傳入初始化方法的引數 t2 = threading.Thread(target=thread2_entry,args=(2,)) #(1,)元組,args=(1,)是入口函式的引數,就是用args傳給他,只能傳元組,一個元素的時候,一定要加逗號,這裡是傳入的是時間 #啟動新執行緒 t1.start() #兩個執行緒的例項化。呼叫start方法 t2.start() start = time() #驗證json等待的時間 #主執行緒等待t1執行緒結束, t1.join() #主執行緒等待t2執行緒結束 t2.join() end = time() #驗證json等待的時間 print(end-start) #驗證json等待的時間 print("main thread end.")
#結果:
# main thread start.
# child thread 1,start at: Sat Nov 10 18:06:26 2018
# child thread 2,start at: Sat Nov 10 18:06:26 2018
# child thread 1,end at: Sat Nov 10 18:06:27 2018
# child thread 2,end at: Sat Nov 10 18:06:28 2018
# 2.0
# main thread end.
多執行緒使用共享資料
共享物件的概念
從例子說起
高鐵上的測試
某個時刻只能一個人使用
進入後往往立刻鎖門(表示已經被使用)
看到的人,門口排隊等待
用完開鎖(表示已經使用完了)
排隊的人中下一個去使用(重複這個過程)
有些資源是某個時刻時刻獨佔使用的
如果不加鎖
某人使用廁所
另一個人也進入使用
發生衝突
鎖保證了
只有一個人去使用
別人必須等待
import threading
from time import sleep,ctime,time
#儲存支付寶賬號餘額
zhifubao = {
"jcy":100000,
"liming":5000,
"wangmin":15000,
"zhaolei":6500000,
}
#執行緒1:滴滴打車處理,引數是使用者賬戶和扣款金額
def thread1_didi_pay(account,amount):
print("* t1:get balance from bank")
balance = zhifubao[account] #通過賬戶把餘額取出來,放到一個變數裡面
#下面的sleep(2)表示一些處理過程中需要花上2秒鐘
print("* t1:do something(like discount lookup) for 2 seconds")
sleep(2)
print("* t1:deduct")
zhifubao[account] = balance - amount #把餘額扣掉
#執行緒2:餘額寶處理,引數是使用者賬戶和當前利息
def thread2_yuebao_interest(account, amount):
print("$ t2:get balance from bank")
balance = zhifubao[account]
# 下面的sleep(1)表示一些處理過程中需要花上1秒鐘
print("$ t2:do something2...... for 2 seconds")
sleep(1)
print("$ t2: add")
zhifubao[account] = balance + amount ##餘額每天的收益
t1 = threading.Thread(target=thread1_didi_pay,args=("jcy",10)) #創立兩個執行緒物件
t2 = threading.Thread(target=thread2_yuebao_interest,args=("jcy",10))
t1.start()
t2.start()
t1.join()
t2.join()
print("finally,jcy balance is %s"%zhifubao["jcy"])
#結果
# * t1:get balance from bank
# * t1:do something(like discount lookup) for 2 seconds
# $ t2:get balance from bank
# $ t2:do something2...... for 2 seconds
# $ t2: add
# * t1:deduct
# finally,jcy balance is 99990
#應該是10萬元
#多個執行緒要訪問共享資料的時候,特別是要修改資料的時候。我們可以使用鎖物件的機制。同時只有一個執行緒處理他的時候,就不會有問題
import threading
from time import sleep,ctime,time
#儲存支付寶賬號餘額
zhifubao = {
"jcy":100000,
"liming":5000,
"wangmin":15000,
"zhaolei":6500000,
}
#呼叫Lock函式,返回一個鎖物件
zhifubao_lock = threading.Lock()
#執行緒1:滴滴打車處理,引數是使用者賬戶和扣款金額
def thread1_didi_pay(account,amount):
#在程式碼訪問共享物件之前,加鎖
#當多個執行緒同時執行lock.acquire()時,
#只有一個執行緒能成功的獲取鎖,然後繼續執行程式碼
#其他執行緒就繼續等待,直到獲得鎖為止
zhifubao_lock.acquire()
print("* t1:get balance from bank")
balance = zhifubao[account] #通過賬戶把餘額取出來,放到一個變數裡面
#下面的sleep(2)表示一些處理過程中需要花上2秒鐘
print("* t1:do something(like discount lookup) for 2 seconds")
sleep(2)
print("* t1:deduct")
zhifubao[account] = balance - amount #把餘額扣掉
#訪問共享物件釋放鎖
#訪問結束後,一定要呼叫Lock物件的release方法,進行解鎖操作
#否則其他等待鎖的執行緒將永遠等待下去
zhifubao_lock.release()
#執行緒2:餘額寶處理,引數是使用者賬戶和當前利息
def thread2_yuebao_interest(account, amount):
zhifubao_lock.acquire() #程式碼訪問共享物件之前,加鎖
print("$ t2:get balance from bank")
balance = zhifubao[account]
# 下面的sleep(1)表示一些處理過程中需要花上1秒鐘
print("$ t2:do something2...... for 2 seconds")
sleep(1)
print("$ t2: add")
zhifubao[account] = balance + amount ##餘額每天的收益
zhifubao_lock.release() #訪問完共享物件 釋放鎖
t1 = threading.Thread(target=thread1_didi_pay,args=("jcy",10)) #創立兩個執行緒物件
t2 = threading.Thread(target=thread2_yuebao_interest,args=("jcy",10))
t1.start()
t2.start()
t1.join()
t2.join()
print("finally,jcy balance is %s"%zhifubao["jcy"])
#結果
# * t1:get balance from bank
# * t1:do something(like discount lookup) for 2 seconds
# * t1:deduct
# $ t2:get balance from bank
# $ t2:do something2...... for 2 seconds
# $ t2: add
# finally,jcy balance is 100000