zoukankan      html  css  js  c++  java
  • 关于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()
    

      

  • 相关阅读:
    eclipse git如何切换分支,拉取代码,合并代码,解决冲突等
    eclipse git提交项目以及down项目大致步骤
    彻底卸载Oracle
    收藏的技术点
    SpringBoot+MyBatis整合报错Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required
    nginx基本配置
    window下命令启动/停止nginx
    springboot 新建的时候 pom 第一行出现红叉,项目可以正常运行
    oracle replace的用法
    启动tomcat出现闪退的原因
  • 原文地址:https://www.cnblogs.com/eternal1025/p/6676699.html
Copyright © 2011-2022 走看看