'''
練習:線程通信:
a、使用Condition實現線程通信
b、使用Queue控制線程通信
c、使用Event控制線程通信
******************************************
Condition類提供幾個方法
acquire([timeout])/release(),調用Lock的acquire()和release()方法
wait([timeout]):導致當前線程進入Condition的等待池等待通知並釋放鎖,直到其他線程調用該Condition的notify()和notify_all()
方法喚醒。在調用該方法的時候可以傳入timeout參數,設置等待時間。
notify():喚醒Condition池內的單個線程,該線程自動調用acquire()方法嘗試加鎖;如果所有線程都在等待池中,則選擇任意一個線程
進行喚醒。
notify_all():喚醒在該Condition等待池中的所有線程並通知它們。
'''
import threading
class Account:
def __init__(self, account_no, balance):
'''構造器函數,初始化賬戶編號、餘額;調用Condition類,並設定flag初始值'''
#封裝賬戶編號和賬戶餘額兩個成員變量
self.account_no = account_no
self._balance = balance
#調用Condition類和定義是否已經存錢的標誌flag
self.cond = threading.Condition()
self._flag = True
def getBalance(self):
'''賬戶餘額獲取函數。因爲賬戶餘額不能隨便修改,所以職位self._balance設置getter方法'''
return self._balance
def draw(self, draw_amount):
'''取錢操作函數,取錢之前設置加鎖'''
self.cond.acquire()
try:
if not self._flag:#如果self.flag爲False,標明賬戶中還沒有存錢進去,取錢方法被阻塞
print("取款操作被阻塞")
self.cond.wait()
else:
print(threading.current_thread().name+"取錢:"+str(draw_amount))
self._balance -=draw_amount
print("賬戶餘額爲:"+str(self._balance))
#設置取款的標誌位False
self._flag = False
#喚醒其他進程
self.cond.notify_all()
finally:
self.cond.release()
def deposit(self, deposit_amount):
'''存錢函數,存錢之前設置加鎖'''
#加鎖
self.cond.acquire()
try:
if self._flag:
print("存款操作被阻塞")
self.cond.acquire()
else:
print(threading.current_thread().name+"存錢:"+str(deposit_amount))
self._balance+=deposit_amount
print("賬戶餘額爲:"+str(self._balance))
#設置存款的標誌位True
self._flag = True
#喚醒其他進程
self.cond.notify_all()
finally:
self.cond.release()
def draw_many(account,draw_amount,max):
#模擬用戶多次花錢;account爲Account的實例對象
for i in range(max):
account.draw(draw_amount)
def deposit_many(account,deposite_amount,max):
#模擬多次存錢;account爲Account的實例對象
for i in range(max):
account.deposit(deposite_amount)
#創建一個賬戶
acc = Account("我的賬戶",800)
#創建一個取錢線程
threading.Thread(name="取錢者", target=draw_many, args=(acc,800,3)).start()
#創建一個存錢線程
threading.Thread(name="存錢甲", target=deposit_many, args=(acc,800,3)).start()