掌握 Python 中的线程间通信:同步和数据共享
线程间通信是指Python多线程程序中线程之间实现通信和同步的过程。
一般来说,Python 中的线程在进程内共享相同的内存空间,这允许它们通过共享变量、对象和线程模块提供的专用同步机制来交换数据并协调其活动。
为了促进线程间通信,线程模块提供了各种同步原语,例如锁、事件、条件和信号量对象。在本教程中,您将学习如何使用事件和条件对象来提供多线程程序中线程之间的通信。
事件对象
事件对象管理内部标志的状态,以便线程可以等待或设置。事件对象提供了控制该标志状态的方法,允许线程根据共享条件同步其活动。
该标志最初为 false,使用 set() 方法变为 true,并使用clear() 方法重置为 false。 wait() 方法会阻塞,直到标志为 true。
以下是事件对象的关键方法 -
- is_set():当且仅当内部标志为 true 时返回 True。
- set():将内部标志设置为 true。所有等待它变为 true 的线程都会被唤醒。一旦标志为 true,调用 wait() 的线程将根本不会阻塞。
- clear():将内部标志重置为 false。随后,调用 wait() 的线程将阻塞,直到调用 set() 再次将内部标志设置为 true。
- wait(timeout=None):阻塞,直到内部标志为 true。如果输入时内部标志为 true,则立即返回。否则,阻塞直到另一个线程调用 set() 将标志设置为 true,或者直到发生可选超时。当超时参数存在且不为 None 时,它应该是一个浮点数,指定操作的超时时间(以秒为单位)。
示例
以下代码尝试模拟由交通信号灯绿色或红色状态控制的交通流。
程序中有两个线程,针对两个不同的功能。 signal_state() 函数定期设置和重置指示信号从绿色变为红色的事件。
Traffic_flow() 函数等待事件被设置,并运行循环直到它保持设置状态。
<前>06前>输出
执行上述代码时,您将得到以下输出 -
<前>15前>条件对象
Python的线程模块中的Condition对象提供了更高级的同步机制。它允许线程在继续之前等待来自另一个线程的通知。 Condition 对象始终与锁相关联,并提供线程之间的信号发送机制。
以下是 threading.Condition() 类的语法 -
<前>23前>以下是 Condition 对象的关键方法 -
- acquire(*args):获取底层锁。该方法调用底层锁上对应的方法;返回值是该方法返回的任何值。
- release():释放底层锁。该方法调用底层锁上对应的方法;没有返回值。 wait(timeout=None):此方法释放底层锁,然后阻塞,直到被另一个线程中相同条件变量的notify()或notify_all()调用唤醒,或者直到发生可选超时。一旦被唤醒或超时,它会重新获取锁并返回。
- wait_for(predicate, timeout=None):此实用程序方法可以重复调用 wait(),直到满足谓词或发生超时。返回值是谓词的最后一个返回值,如果方法超时,则计算结果为 False。
- notify(n=1):该方法最多唤醒n个等待条件变量的线程;如果没有线程在等待,则它是无操作。
- notify_all():唤醒所有在此条件下等待的线程。该方法的作用类似于notify(),但唤醒所有等待线程而不是一个。如果调用此方法时调用线程尚未获取锁,则会引发 RuntimeError。
示例
此示例演示了使用 Python 线程模块的 Condition 对象进行线程间通信的简单形式。这里 thread_a 和 thread_b 使用 Condition 对象进行通信,thread_a 等待直到收到来自 thread_b 的通知。 thread_b 在通知 thread_a 之前休眠 2 秒,然后完成。
<前>37前>输出
执行上述代码时,您将得到以下输出 -
<前>45前>示例
这是另一个代码,演示了如何使用 Condition 对象提供线程之间的通信。其中,线程t2运行taskB()函数,线程t1运行taskA()函数。 t1线程获取条件并通知它。
此时t2线程处于等待状态。条件释放后,等待线程继续消耗通知函数生成的随机数。
<前>53前>当您执行此代码时,它将产生以下输出 -
<前>66前>Python