Python-线程间通信


线程共享分配给进程的内存。结果,同一进程中的线程可以相互通信。为了方便线程间通信,线程模块提供了Event对象和Condition对象。

事件对象

事件对象管理内部标志的状态。该标志最初为 false,使用 set() 方法变为 true,并使用clear() 方法重置为 false。wait() 方法会阻塞,直到标志为 true。

事件对象的方法 -

is_set() 方法

当且仅当内部标志为 true 时返回 True。

set() 方法

将内部标志设置为 true。所有等待它变为 true 的线程都会被唤醒。一旦标志为 true,调用 wait() 的线程将根本不会阻塞。

清除()方法

将内部标志重置为 false。随后,调用 wait() 的线程将阻塞,直到调用 set() 再次将内部标志设置为 true。

等待(超时=无)方法

阻塞直到内部标志为真。如果输入时内部标志为 true,则立即返回。否则,阻塞直到另一个线程调用 set() 将标志设置为 true,或者直到发生可选超时。

当超时参数存在且不为 None 时,它​​应该是一个浮点数,指定操作的超时时间(以秒为单位)。

例子

以下代码尝试模拟由交通信号灯绿色或红色状态控制的交通流。

程序中有两个线程,针对两个不同的功能。signal_state() 函数定期设置和重置指示信号从绿色变为红色的事件。

Traffic_flow() 函数等待事件被设置,并运行循环直到它保持设置状态。

from threading import *
import time

def signal_state():
   while True:
      time.sleep(5)
      print("Traffic Police Giving GREEN Signal")
      event.set()
      time.sleep(10)
      print("Traffic Police Giving RED Signal")
      event.clear()

def traffic_flow():
   num=0
   while num<10:
      print("Waiting for GREEN Signal")
      event.wait()
      print("GREEN Signal ... Traffic can move")
      while event.is_set():
         num=num+1
         print("Vehicle No:", num," Crossing the Signal")
         time.sleep(2)
      print("RED Signal ... Traffic has to wait")

event=Event()
t1=Thread(target=signal_state)
t2=Thread(target=traffic_flow)
t1.start()
t2.start()

输出

Waiting for GREEN Signal
Traffic Police Giving GREEN Signal
GREEN Signal ... Traffic can move
Vehicle No: 1 Crossing the Signal
Vehicle No: 2 Crossing the Signal
Vehicle No: 3 Crossing the Signal
Vehicle No: 4 Crossing the Signal
Vehicle No: 5 Crossing the Signal
Signal is RED
RED Signal ... Traffic has to wait
Waiting for GREEN Signal
Traffic Police Giving GREEN Signal
GREEN Signal ... Traffic can move
Vehicle No: 6 Crossing the Signal
Vehicle No: 7 Crossing the Signal
Vehicle No: 8 Crossing the Signal
Vehicle No: 9 Crossing the Signal
Vehicle No: 10 Crossing the Signal

条件对象

线程模块类中的条件类实现条件变量对象。Condition 对象强制一个或多个线程等待,直到另一线程通知为止。条件与可重入锁相关联。条件对象具有 acquire() 和 release() 方法,它们调用关联锁的相应方法。

threading.Condition(lock=None)

以下是 Condition 对象的方法 -

获取(*args)

获取底层锁。该方法调用底层锁上对应的方法;返回值是该方法返回的任何值。

发布()

释放底层锁。该方法调用底层锁上对应的方法;没有返回值。

等待(超时=无)

此方法释放底层锁,然后阻塞,直到它被另一个线程中同一条件变量的notify() 或notify_all() 调用唤醒,或者直到发生可选超时。一旦被唤醒或超时,它会重新获取锁并返回。

wait_for(谓词,超时=无)

此实用程序方法可以重复调用 wait() 直到满足谓词,或者直到发生超时。返回值是谓词的最后一个返回值,如果方法超时,则计算结果为 False。

通知(n=1)

该方法最多唤醒n个等待条件变量的线程;如果没有线程在等待,则它是无操作。

通知所有()

唤醒所有在此条件下等待的线程。该方法的作用类似于notify(),但唤醒所有等待线程而不是一个。如果调用此方法时调用线程尚未获取锁,则会引发 RuntimeError。

例子

在以下代码中,线程 t2 运行 taskB() 函数,线程 t1 运行 taskA() 函数。t1线程获取条件并通知它。此时t2线程处于等待状态。条件释放后,等待线程继续消耗通知函数生成的随机数。

from threading import *
import time
import random

numbers=[]
def taskA(c):
   while True:
      c.acquire()
      num=random.randint(1,10)
      print("Generated random number:", num)
      numbers.append(num)
      print("Notification issued")
      c.notify()
      c.release()
      time.sleep(5)

def taskB(c):
   while True:
      c.acquire()
      print("waiting for update")
      c.wait()
      print("Obtained random number", numbers.pop())
      c.release()
      time.sleep(5)

c=Condition()
t1=Thread(target=taskB, args=(c,))
t2=Thread(target=taskA, args=(c,))
t1.start()
t2.start()

当您执行此代码时,它将产生以下输出-

waiting for update
Generated random number: 4
Notification issued
Obtained random number 4
waiting for update
Generated random number: 6
Notification issued
Obtained random number 6
waiting for update
Generated random number: 10
Notification issued
Obtained random number 10
waiting for update