python多线程模型event研究分析
事件
这是一个非常简单的机构。一个线程启动一个事件,然后其他线程等待信号。
让我们回到生产者和消费者的例子,我们将使用event 来替换 condition。源码你可以在threads/event.py里找到。
首先是生产者类传递一个event实例来替换之前的condition实例。整数在不断的被添加到列表中,
事件实例在不断的通知消费者。事件实例默认被清空。
- class Producer(threading.Thread):
- """
- Produces random integers to a list
- """
- def __init__(self, integers, event):
- """
- Constructor.
- @param integers list of integers
- @param event event synchronization object
- """
- threading.Thread.__init__(self)
- self.integers = integers
- self.event = event
- def run(self):
- """
- Thread run method. Append random integers to the integers list
- at random time.
- """
- while True:
- integer = random.randint(0, 256)
- self.integers.append(integer)
- print '%d appended to list by %s' % (integer, self.name)
- print 'event set by %s' % self.name
- self.event.set()
- self.event.clear()
- print 'event cleared by %s' % self.name
- time.sleep(1)
下面是消费者类。我们也传值以恶搞事件实例给构造器。生产者实例将被wait函数阻塞,直到事件实例
发去信号,有东西可以被消费。
- class Consumer(threading.Thread):
- """
- Consumes random integers from a list
- """
- def __init__(self, integers, event):
- """
- Constructor.
- @param integers list of integers
- @param event event synchronization object
- """
- threading.Thread.__init__(self)
- self.integers = integers
- self.event = event
- def run(self):
- """
- Thread run method. Consumes integers from list
- """
- while True:
- self.event.wait()
- try:
- integer = self.integers.pop()
- print '%d popped from list by %s' % (integer, self.name)
- except IndexError:
- # catch pop on empty list
- time.sleep(1)
下面是一次运行后的结果,thread-1将124添加到列表,然后触发事件通知消费者。消费者调用
wait停止阻塞,然后将整数在list中清除
$ python event.py
124 appended to list by Thread-1
event set by Thread-1
event cleared by Thread-1
124 popped from list by Thread-2
223 appended to list by Thread-1
event set by Thread-1
event cleared by Thread-1
223 popped from list by Thread-2
我们看一下python内部实现的原理。首先,是一个事件的构造器。有一个加锁的codition实例,用来
保护事件的标志,并且在事件被调用时通知其他线程
- class _Event(_Verbose):
- def __init__(self, verbose=None):
- _Verbose.__init__(self, verbose)
- self.__cond = Condition(Lock())
- self.__flag = False
关于set方法,它将标志位设置成True并且通知其他线程。condition对象被用于局部保护在标志被改变的时候
- def set(self):
- self.__cond.acquire()
- try:
- self.__flag = True
- self.__cond.notify_all()
- finally:
- self.__cond.release()
clear 方法将标志置成false
- def clear(self):
- self.__cond.acquire()
- try:
- self.__flag = False
- finally:
- self.__cond.release()
wait方法阻塞直到set方法被调用。在标志被设置的时候,wait就什么都不做
- def wait(self, timeout=None):
- self.__cond.acquire()
- try:
- if not self.__flag:
- self.__cond.wait(timeout)
- finally:
- self.__cond.release()