已知小明和其弟弟小白每月都需要生活費,二人同時從同一個賬戶中取錢,兩人每人每月需要1000元,賬戶中現有余額3200元,如果卡內余額大於2000元,則父母不會存入,如果卡內余額小於2000元,則父母當月會向卡內一次存入3500元。4個月后,卡內所剩余額是多少?
這道題可以運用多線程互相搶奪的性質來寫
import threading import time lock=threading.Lock() money=3200 def take(name): for i in range(4): print(i) global money lock.acquire() money-=1000 print(name,"取走1000元,卡里余額是:",money) lock.release() time.sleep(1.1) def save(): global money for i in range(4): if money>2000: pass else: money+=3500 print("父母存入了3500元錢,卡內余額為:",money) time.sleep(1) t1=threading.Thread(target=save) t2=threading.Thread(target=take,args=("小明",)) t3=threading.Thread(target=take,args=("小白",)) t1.start() t2.start() t3.start()
因為for循環寫在鎖外,所以i會成為搶奪的對象,同時每個線程都會將循環一遍,當循環的范圍大時,會亂序,但是每個線程都會循環一遍,結果如下
def take(name): for i in range(4): print(i) global money lock.acquire() money-=1000 print(name,"取走1000元,卡里余額是:",money) lock.release() #time.sleep(1.1)
0 小明 取走1000元,卡里余額是: 2200 1 小明 取走1000元,卡里余額是: 1200 2 小明 取走1000元,卡里余額是: 200 3 小明 取走1000元,卡里余額是: -800 0 小白 取走1000元,卡里余額是: -1800 1 小白 取走1000元,卡里余額是: -2800 2 小白 取走1000元,卡里余額是: -3800 3 小白 取走1000元,卡里余額是: -4800
time.sleep()的作用
由上邊結果可以看出兩個線程都循環了四次,而小明和小白這四個月每個月都需要取錢,所以兩個人都需要取四次,而且每個月取的錢數也是一樣的,他們可以運行同一個函數,這樣顯得簡潔又高大上,因此可以通過線程搶奪的性質和線程休眠來做這道題。
使用time.sleep()是為了讓兩個線程運行的順序成為(以i為代表)0,0,1,1,2,2,3,3。當小明或小白搶到時,它通過鎖取完錢后,執行到sleep(),這個線程就會休眠,這時就剩另外一個線程來運行,當它取完錢,同樣休眠,父母存錢的線路也是同樣的。
一個線程運行一次就休眠,讓路給其他沒運行過的線程讓他們來運行,從而使他們可以幾個線程一循環,例如,t1,t2,t3三個線程,他的運行順序就是(t1,t2,t3),(t1,t2,t3),(t1,t2,t3(這三個線程的順序是亂序的,沒有規律))····
最終完整的代碼結果為
0 小明 取走1000元,卡里余額是: 2200 0 小白 取走1000元,卡里余額是: 1200 父母存入了3500元錢,卡內余額為: 4700 1 小白 取走1000元,卡里余額是: 3700 1 小明 取走1000元,卡里余額是: 2700 2 小白 取走1000元,卡里余額是: 1700 2 小明 取走1000元,卡里余額是: 700 父母存入了3500元錢,卡內余額為: 4200 3 3 小白 取走1000元,卡里余額是: 3200 小明 取走1000元,卡里余額是: 2200