python处理多并发

python处理多并发

在python中实现多并发可以通过多线程,多进程或者异步I/O方式实现,各种方法适合的应用场景不同,具体选择取决于你的任务类型和资源需求

多线程

多线程适合于I/O密集型任务,因为线程相对轻量,可以方便地切换来优化等待时间

import threading

def worker(num):
    print(f'Thread {num} is running')

threads = []
for i in range(5):
    thread = threading.Thread(target=worker, args=(i,))
    threads.append(thread)
    thread.start()

for thread in threads:
    thread.join()

多进程

多进程适用于cpu密集型任务,因为每个进程被分配独立的内存空间,能充分利用多核 CPU 的优势。

from multiprocessing import Process

def worker(num):
    print(f'Process {num} is running')

processes = []
for i in range(5):
    process = Process(target=worker, args=(i,))
    processes.append(process)
    process.start()

for process in processes:
    process.join()

异步 I/O

异步 I/O 非常适合大量 I/O 操作,如访问网络、文件读取等,能够在等待 I/O 完成时执行其他任务。

import asyncio

async def worker(num):
    print(f'Worker {num} is starting')
    await asyncio.sleep(2)  # 模拟 I/O 操作
    print(f'Worker {num} finished')

async def main():
    tasks = [worker(i) for i in range(5)]
    await asyncio.gather(*tasks)

asyncio.run(main())

选择合适的方法

  • 多线程:适用于 I/O 密集型任务。注意 GIL(全局解释器锁)的影响,在 Python 中多线程不适合 CPU 密集型任务。
  • 多进程:适用于 CPU 密集型任务,无需考虑 GIL,因为每个进程有独立的解释器实例。
  • 异步 I/O:适用于网络请求、文件读写等异步操作,能够高效地处理大量 I/O 请求。

注意事项

  • 在使用多线程和多进程时,注意共享资源的同步,以避免竞争条件。
  • 异步编程可能需要额外考虑依赖库或代码结构的重构,以支持异步编程风格。
  • 对于简单的任务,可以从线程开始,对于更复杂的任务则选择合适的并发模型。

线程资源同步

使用threading.Lock

threading.Lock 是最基础的锁机制。它可以用来确保某一时刻只有一个线程可以访问共享资源。

import threading

# 共享资源
shared_data = 0

# 锁对象
lock = threading.Lock()

def worker():
    global shared_data
    
    # 进入临界区
    with lock:
        # 操作共享资源
        for _ in range(100000):
            shared_data += 1

# 创建线程
threads = [threading.Thread(target=worker) for _ in range(5)]

# 启动线程
for thread in threads:
    thread.start()

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

print(f'Shared Data: {shared_data}')

在这个例子中,我们创建了多个线程,它们会同时尝试更新共享变量shared_data.通过使用lock,确保对于shared_data的增量操作是原子的,即被完整执行的

使用threading.RLock

threading.RLock 是可重入锁,允许同一线程在不产生死锁的情况下多次获得锁。这在某个线程需要多次访问同一使用 Lock 保证同步的代码段时非常有用。

import threading

lock = threading.RLock()

def recursive_count(n):
    with lock:
        if n > 0:
            print(n)
            recursive_count(n - 1)

t = threading.Thread(target=recursive_count, args=(5,))
t.start()
t.join()

使用 threading.Condition

threading.Condition 允许线程等待某个条件发生。它实际上是 LockEvents 的结合体,适用于更复杂的同步需求。

import threading

# 共享资源
shared_data = []

# 条件变量
condition = threading.Condition()

def producer():
    global shared_data
    with condition:
        for i in range(5):
            shared_data.append(i)
            print(f'Produced {i}')
            condition.notify()  # 通知消费者
        
def consumer():
    global shared_data
    with condition:
        while True:
            condition.wait()  # 等待生产者通知
            item = shared_data.pop(0)
            print(f'Consumed {item}')
            if not shared_data:
                break

# 启动生产者和消费者线程
t1 = threading.Thread(target=producer)
t2 = threading.Thread(target=consumer)
t1.start()
t2.start()
t1.join()
t2.join()

选择合适的同步机制

  • 使用 Lock 来保护对共享资源的简洁访问。
  • 使用 RLock 如果同一个线程需要多次进入锁定部分。
  • 使用 Condition 处理复杂的状态和等待信号的场景。
posted @ 2025-03-11 22:14  小郑[努力版]  阅读(22)  评论(0)    收藏  举报