已知小明和其弟弟小白每月都需要生活费,二人同时从同一个账户中取钱,两人每人每月需要1000元,账户中现有余额3200元,如果卡内余额大于2000元,则父母不会存入,如果卡内余额小于2000元,则父母当月会向卡内一次存入3500元。4个月后,卡内所剩余额是多少?
这道题可以运用多线程互相抢夺的性质来写
importthreadingimporttime
lock=threading.Lock()
money=3200
deftake(name):for i in range(4):print(i)globalmoney
lock.acquire()
money-=1000
print(name,"取走1000元,卡里余额是:",money)
lock.release()
time.sleep(1.1)defsave():globalmoneyfor 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元,卡里余额是:22000
小白 取走1000元,卡里余额是:1200父母存入了3500元钱,卡内余额为:4700
1小白 取走1000元,卡里余额是:3700
1小明 取走1000元,卡里余额是:2700
2小白 取走1000元,卡里余额是:1700
2小明 取走1000元,卡里余额是:700父母存入了3500元钱,卡内余额为:4200
3
3小白 取走1000元,卡里余额是:3200小明 取走1000元,卡里余额是:2200