在 Python 中,多线程 是一种并发编程的技术,用于同时执行多个任务。Python 提供了多个模块来处理多线程,最常用的是 threading 模块。多线程可以让您在一个程序中同时执行多个任务,但需要注意的是,由于 Python 的全局解释器锁(GIL)的存在,线程在执行计算密集型任务时可能没有预期的性能提升。然而,线程在 I/O 密集型任务(如网络请求、文件操作等)中非常有效。

目录

  1. Python 多线程基础
  2. 创建和启动线程
  3. 线程同步
  4. 线程池
  5. 线程生命周期和异常处理
  6. 参考资料

1. Python 多线程基础

Python 的 threading 模块提供了对多线程的支持。在多线程程序中,程序中的多个线程可以同时运行,这些线程共享同一内存空间,可以进行并发的任务处理。

1.1 threading 模块

threading 模块提供了与线程相关的类和方法,常用的类包括:

  • Thread: 用于创建和管理线程。
  • Lock, RLock, Semaphore: 用于线程同步。
  • Event: 用于线程之间的信号通信。

2. 创建和启动线程

在 Python 中,您可以通过继承 threading.Thread 类来创建线程,也可以使用 Thread 类的构造函数来创建线程实例。

2.1 使用 Thread 类创建线程

import threading
import time

# 定义线程要执行的任务
def print_numbers():
    for i in range(5):
        print(f"线程 {threading.current_thread().name} 打印数字: {i}")
        time.sleep(1)

# 创建线程实例
thread1 = threading.Thread(target=print_numbers, name="Thread-1")
thread2 = threading.Thread(target=print_numbers, name="Thread-2")

# 启动线程
thread1.start()
thread2.start()

# 等待线程结束
thread1.join()
thread2.join()

print("所有线程执行完毕!")

2.2 继承 Thread 类创建线程

您也可以通过继承 threading.Thread 类来创建线程,并重写 run 方法。

import threading
import time

class MyThread(threading.Thread):
    def run(self):
        for i in range(5):
            print(f"线程 {self.name} 打印数字: {i}")
            time.sleep(1)

# 创建线程实例
thread1 = MyThread()
thread2 = MyThread()

# 启动线程
thread1.start()
thread2.start()

# 等待线程结束
thread1.join()
thread2.join()

print("所有线程执行完毕!")


3. 线程同步

由于多个线程共享同一内存空间,因此在执行某些任务时,可能会发生数据竞态,即多个线程同时访问和修改共享资源,导致数据不一致。为了防止这种情况,Python 提供了多种同步机制。

3.1 使用 Lock 进行线程同步

Lock 是 Python 提供的一种同步机制,用于防止多个线程同时访问共享资源。通过 acquire() 方法获取锁,release() 方法释放锁。

import threading

# 定义共享资源
counter = 0
lock = threading.Lock()

def increment():
    global counter
    for _ in range(100000):
        with lock:  # 使用 lock 确保线程安全
            counter += 1

# 创建多个线程
threads = []
for _ in range(10):
    thread = threading.Thread(target=increment)
    threads.append(thread)
    thread.start()

# 等待所有线程完成
for thread in threads:
    thread.join()

print(f"最终 counter 值: {counter}")

在这个例子中,lock 用于确保 counter 的修改在多线程环境下是线程安全的。

3.2 使用 RLock 进行递归锁

RLock 是一个可以被同一个线程多次获取的锁。如果一个线程已经持有 RLock,它可以再次获取这个锁而不会阻塞自己。

import threading

rlock = threading.RLock()

def recursive_function(n):
    with rlock:
        print(f"执行递归函数 {n}")
        if n > 0:
            recursive_function(n - 1)

# 启动线程
thread = threading.Thread(target=recursive_function, args=(5,))
thread.start()
thread.join()


4. 线程池

线程池(ThreadPoolExecutor)是 Python 3.2 引入的一个功能,允许您轻松地管理大量线程。使用线程池,您可以避免手动创建和管理线程,而是将任务提交给线程池,线程池会自动处理线程的创建和销毁。

4.1 使用 ThreadPoolExecutor 创建线程池

from concurrent.futures import ThreadPoolExecutor
import time

def task(n):
    print(f"线程 {n} 开始执行")
    time.sleep(2)
    print(f"线程 {n} 执行完毕")

# 创建线程池
with ThreadPoolExecutor(max_workers=3) as executor:
    # 提交多个任务
    for i in range(5):
        executor.submit(task, i)

在这个例子中,最多有 3 个线程同时工作,其他线程将排队等待空闲的线程。


5. 线程生命周期和异常处理

5.1 线程生命周期

线程的生命周期包括以下几个状态:

  • 创建:线程对象被创建。
  • 启动:调用 start() 方法开始执行线程。
  • 运行:线程开始执行任务。
  • 结束:任务执行完毕,线程退出。

5.2 线程异常处理

线程中的异常不会自动传递到主线程,因此需要手动处理异常。可以使用 try...except 语句捕获线程中的异常。

import threading

def task():
    try:
        x = 1 / 0  # 故意抛出除以零异常
    except Exception as e:
        print(f"线程发生异常: {e}")

# 创建线程并启动
thread = threading.Thread(target=task)
thread.start()
thread.join()


6. 参考资料

出站链接

站内链接

通过这些方法,您可以利用 Python 强大的 threading 模块实现高效的多线程程序,满足不同并发需求。