关于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()

  

你可能感兴趣的