📜  Python|线程间通信 |第 2 组(1)

📅  最后修改于: 2023-12-03 15:34:21.069000             🧑  作者: Mango

Python 线程间通信 | 第 2 组

在 Python 中,线程通常是并发程序的基础。线程的并发性很大程度上取决于线程之间的通信。线程之间的通信可以通过共享数据实现。然而,共享数据可能导致数据竞争和死锁的问题。Python 中有多种线程间通信机制,例如条件变量、互斥锁和队列等。在本文中,我们将详细介绍这些机制和它们的使用。

条件变量

条件变量是 Python 中一种非常有用的线程间通信机制。条件变量可以用于线程间通信和同步。条件变量通常会使用锁来保护内部状态,并在某些条件下等待或通知其他线程。Python 中有两个内置的条件变量:threading.Conditionasyncio.Conditionthreading.Condition 适用于常规线程,而 asyncio.Condition 适用于异步线程。

一个典型的条件变量应用需要有以下几个步骤:

  1. 创建一个锁对象和一个条件变量对象。
  2. 在一个线程中获取锁之后,检查条件是否为真。如果条件为假,则调用 condition.wait() 方法暂停当前线程,直到条件变为真。
  3. 在另一个线程中更改共享状态并通知等待的线程。这通常是通过调用 condition.notify()condition.notify_all() 方法实现的。
  4. 当线程被唤醒时,它会重新获取锁,然后重新检查条件。如果条件仍然为假,则线程会继续等待。

下面是一个简单的条件变量应用的示例代码:

import threading

# 创建一个锁对象和条件变量对象
lock = threading.Lock()
condition = threading.Condition(lock)

# 共享状态
counter = 0

# 线程函数,用于增加计数器的值并通知其他线程
def worker():
    global counter
    for _ in range(10):
        with lock:
            counter += 1
            print(f'counter={counter}')
            # 通知其他线程
            condition.notify_all()

# 主函数,用于检查计数器的值并等待通知
def main():
    global counter
    with lock:
        # 等待计数器的值为 5
        while counter < 5:
            condition.wait()
    print(f'counter={counter}')

if __name__ == '__main__':
    # 创建两个线程,一个用于增加计数器的值,一个用于检查计数器的值
    t1 = threading.Thread(target=worker)
    t2 = threading.Thread(target=main)
    t1.start()
    t2.start()
    t1.join()
    t2.join()
互斥锁

互斥锁是另一种常用的线程间通信机制。互斥锁用于保护共享资源,只有一个线程可以持有该锁。当一个线程想要访问共享资源时,它必须首先获取锁。如果锁已经被另一个线程持有,则该线程会被阻塞,直到锁被释放为止。

Python 中的互斥锁有两种实现:threading.Lockmultiprocessing.Lockthreading.Lock 可用于多个线程,而 multiprocessing.Lock 仅适用于多个进程。

下面是一个简单的互斥锁的示例代码:

import threading

# 创建一个互斥锁对象
lock = threading.Lock()

# 共享状态
counter = 0

# 线程函数,用于增加计数器的值
def worker():
    global counter
    for _ in range(10):
        with lock:
            counter += 1
            print(f'counter={counter}')

if __name__ == '__main__':
    # 创建两个线程,一个用于增加计数器的值,一个用于检查计数器的值
    t1 = threading.Thread(target=worker)
    t2 = threading.Thread(target=worker)
    t1.start()
    t2.start()
    t1.join()
    t2.join()
队列

队列是用于线程间通信和同步的另一种重要技术。队列是一种有序的数据结构,可以用于线程之间传递数据。Python 中有三种类型的队列:queue.Queuemultiprocessing.Queueasyncio.Queue

队列有两种类型:阻塞和非阻塞。阻塞队列是一种线程安全的队列,它会在队列为空时阻塞获取操作,并在队列满时阻塞插入操作。非阻塞队列则不会阻塞任何操作,如果操作无法立即执行,则会引发异常。

下面是一个简单的队列的示例代码:

import queue
import threading

# 创建一个阻塞队列对象
q = queue.Queue()

# 线程函数,将数据放入队列中
def worker():
    for i in range(10):
        q.put(i)

# 主函数,从队列中获取数据
def main():
    while True:
        try:
            data = q.get(block=True, timeout=None)
        except queue.Empty:
            break
        print(f'data={data}')

if __name__ == '__main__':
    # 创建一个线程,用于向队列中放入数据
    t = threading.Thread(target=worker)
    t.start()
    main()
    t.join()
总结

Python 中提供了众多的线程间通信和同步机制,本文介绍了其中的条件变量、互斥锁和队列三种机制。根据实际需求,可以选择适当的机制来实现线程间通信和同步,以确保多个线程之间的正确交互和共享数据的安全性。