已知小明和其弟弟小白每月都需要生活费,二人同时从同一个账户中取钱,两人每人每月需要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