關於Python多線程condition變量的應用


'''
所謂條件變量,即這種機制是在滿足了特定的條件后,線程才可以訪問相關的數據。
它使用Condition類來完成,由於它也可以像鎖機制那樣用,所以它也有acquire方法和release方法,而且它還有wait,notify,notifyAll方法。

一個簡單的生產消費者模型,通過條件變量的控制產品數量的增減,調用一次生產者產品就是+1,調用一次消費者產品就會-1.
使用 Condition 類來完成,由於它也可以像鎖機制那樣用,所以它也有 acquire 方法和 release 方法,而且它還有
wait, notify, notifyAll 方法。
'''

import threading
import queue, time, random

# 產品類
class Goods:
    def __init__(self):
        self.count = 0

    def add(self, num=1):
        self.count += num

    def sub(self):
        if self.count >= 0:
            self.count -= 1

    def empty(self):
        return self.count <= 0

# 生產者
class Producer(threading.Thread):

    def __init__(self, condition, goods, sleeptime=1):
        threading.Thread.__init__(self)
        self.cond = condition
        self.goods = goods
        self.sleeptime = sleeptime

    def run(self):
        cond = self.cond
        goods = self.goods
        while True:
            # 鎖住資源
            cond.acquire()
            goods.add()
            print("產品數量:", goods.count, "生產者線程")
            # 喚醒所有等待的線程 -> 其實就是喚醒消費者進程
            cond.notifyAll()
            # 解鎖資源
            cond.release()
            time.sleep(self.sleeptime)

# 消費者
class Consumer(threading.Thread):
    def __init__(self, condition, goods, sleeptime=2):
        threading.Thread.__init__(self)
        self.cond = condition
        self.goods = goods
        self.sleeptime = sleeptime

    def run(self):
        cond = self.cond
        goods = self.goods
        while True:
            time.sleep(self.sleeptime)
            # 鎖住資源
            cond.acquire()
            # 如無產品則讓線程等待
            while goods.empty():
                cond.wait()
            goods.sub()
            print("產品數量:", goods.count, "消費者線程")
            # 解鎖資源
cond.release()
g = Goods() c = threading.Condition() pro = Producer(c, g) pro.start() con = Consumer(c, g) con.start()

 

'''

event 對象最好單次使用,就是說,你創建一個 event 對象,讓某個線程等待這個對象,
一旦這個對象被設置為真,你就應該丟棄它。盡管可以通過 clear() 方法來重置 event 對
象,但是很難確保安全地清理 event 對象並對它重新賦值。很可能會發生錯過事件、死鎖
或者其他問題(特別是,你無法保證重置 event 對象的代碼會在線程再次等待這個 event對象之前執行)。如果一個線程需要不停地重復使用 event 對象,你最好使用 Condition
對象來代替。下面的代碼使用 Condition 對象實現了一個周期定時器,每當定時器超時的
時候,其他線程都可以監測到:
'''

import threading
import time

class PeriodicTimer:
	def __init__(self, interval):
		self._interval = interval
		self._flag = 0
		self._cv = threading.Condition()

	def start(self):
		t = threading.Thread(target=self.run)
		t.daemon = False
		t.start()

	def run(self):
		# Run the timer and notify waiting threads after each interval
		while True:
			time.sleep(self._interval)
			with self._cv:
				self._flag ^= 1
				self._cv.notify_all()

	def wait_for_tick(self):
		# wait for the next tick of the timer

		with self._cv:
			last_flag = self._flag
			while last_flag == self._flag:
				self._cv.wait()

ptimer = PeriodicTimer(2)
ptimer.start()

def countdown(nticks):
	while nticks > 0:
		ptimer.wait_for_tick()
		print('T-minus', nticks)
		nticks -= 1

def countup(last):
	n = 0
	while n < last:
		ptimer.wait_for_tick()
		print('Counting', n)
		n += 1


threading.Thread(target=countdown, args=(10,)).start()
threading.Thread(target=countup, args=(10,)).start()

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM