【Python】-線程同步(一)-Condition

'''
練習:線程通信:
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()

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章