python多线程模型event研究分析

事件

这是一个非常简单的机构。一个线程启动一个事件,然后其他线程等待信号。

让我们回到生产者和消费者的例子,我们将使用event 来替换 condition。源码你可以在threads/event.py里找到。


首先是生产者类传递一个event实例来替换之前的condition实例。整数在不断的被添加到列表中,

事件实例在不断的通知消费者。事件实例默认被清空。




  1. class Producer(threading.Thread):

  2.     """

  3.    Produces random integers to a list

  4.    """

  5.  

  6.     def __init__(self, integers, event):

  7.         """

  8.        Constructor.

  9.  

  10.        @param integers list of integers

  11.        @param event event synchronization object

  12.        """

  13.         threading.Thread.__init__(self)

  14.         self.integers = integers

  15.         self.event = event

  16.  

  17.     def run(self):

  18.         """

  19.        Thread run method. Append random integers to the integers list

  20.        at random time.

  21.        """

  22.         while True:

  23.             integer = random.randint(0, 256)

  24.             self.integers.append(integer)

  25.             print '%d appended to list by %s' % (integer, self.name)

  26.             print 'event set by %s' % self.name

  27.             self.event.set()

  28.             self.event.clear()

  29.             print 'event cleared by %s' % self.name

  30.             time.sleep(1)



下面是消费者类。我们也传值以恶搞事件实例给构造器。生产者实例将被wait函数阻塞,直到事件实例

发去信号,有东西可以被消费。




  1. class Consumer(threading.Thread):

  2.     """

  3.    Consumes random integers from a list

  4.    """

  5.  

  6.     def __init__(self, integers, event):

  7.         """

  8.        Constructor.

  9.  

  10.        @param integers list of integers

  11.        @param event event synchronization object

  12.        """

  13.         threading.Thread.__init__(self)

  14.         self.integers = integers

  15.         self.event = event

  16.  

  17.     def run(self):

  18.         """

  19.        Thread run method. Consumes integers from list

  20.        """

  21.         while True:

  22.             self.event.wait()

  23.             try:

  24.                 integer = self.integers.pop()

  25.                 print '%d popped from list by %s' % (integer, self.name)

  26.             except IndexError:

  27.                 # catch pop on empty list

  28.                 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实例,用来

保护事件的标志,并且在事件被调用时通知其他线程




  1. class _Event(_Verbose):

  2.     def __init__(self, verbose=None):

  3.         _Verbose.__init__(self, verbose)

  4.         self.__cond = Condition(Lock())

  5.         self.__flag = False



关于set方法,它将标志位设置成True并且通知其他线程。condition对象被用于局部保护在标志被改变的时候




  1. def set(self):

  2.     self.__cond.acquire()

  3.     try:

  4.         self.__flag = True

  5.         self.__cond.notify_all()

  6.     finally:

  7.         self.__cond.release()



clear 方法将标志置成false




  1. def clear(self):

  2.     self.__cond.acquire()

  3.     try:

  4.         self.__flag = False

  5.     finally:

  6.         self.__cond.release()



wait方法阻塞直到set方法被调用。在标志被设置的时候,wait就什么都不做




  1. def wait(self, timeout=None):

  2.     self.__cond.acquire()

  3.     try:

  4.         if not self.__flag:

  5.             self.__cond.wait(timeout)

  6.     finally:

  7.         self.__cond.release()