【30天玩转python】并发编程

并发编程

并发编程是指在同一时间处理多个任务的能力,任务可能是独立的,也可能是相互交错执行。并发编程的目标是充分利用 CPU 的多核处理能力,提升程序的执行效率。Python 提供了多种并发编程方法,包括多线程、多进程和异步编程。本文将介绍 Python 中的几种常见并发编程方式。


1. 多线程

多线程是一种常见的并发编程方式,它允许程序在同一进程中同时运行多个线程。Python 的 threading 模块提供了创建和管理线程的功能。

1.1 使用 threading 模块

通过 threading 模块可以轻松地创建和管理线程。下面是一个创建多线程的简单示例:

示例:创建多线程

import threading
import time

def worker(name):
    print(f"线程 {name} 开始工作")
    time.sleep(2)
    print(f"线程 {name} 结束工作")

# 创建多个线程
threads = []
for i in range(3):
    thread = threading.Thread(target=worker, args=(i,))
    threads.append(thread)
    thread.start()

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

print("所有线程完成")
1.2 线程的同步

由于线程之间是并发执行的,所以需要确保对共享数据的访问是安全的。Python 提供了 Lock(锁)机制来保证线程的同步。

示例:使用锁机制

import threading

counter = 0
lock = threading.Lock()

def increment():
    global counter
    with lock:
        for _ in range(100000):
            counter += 1

threads = []
for _ in range(2):
    thread = threading.Thread(target=increment)
    threads.append(thread)
    thread.start()

for thread in threads:
    thread.join()

print(f"计数器值为: {counter}")

在这个示例中,使用 lock 来确保多个线程不会同时修改 counter,避免竞态条件。


2. 多进程

多进程是一种并发编程方式,它通过在多个进程中运行任务来实现并发。每个进程都有自己的内存空间,因此多进程可以绕过 Python 中的全局解释器锁(GIL)限制,更适合 CPU 密集型任务。

2.1 使用 multiprocessing 模块

multiprocessing 模块用于创建和管理进程。与线程类似,进程可以并发执行任务,但进程之间的数据是独立的,无法直接共享。

示例:创建多进程

import multiprocessing
import time

def worker(name):
    print(f"进程 {name} 开始工作")
    time.sleep(2)
    print(f"进程 {name} 结束工作")

if __name__ == "__main__":
    processes = []
    for i in range(3):
        process = multiprocessing.Process(target=worker, args=(i,))
        processes.append(process)
        process.start()

    for process in processes:
        process.join()

    print("所有进程完成")
2.2 进程间通信

由于进程之间的数据是独立的,Python 提供了 QueuePipe 等机制来实现进程间通信(IPC,Inter-Process Communication)。

示例:使用 Queue 进行进程间通信

import multiprocessing

def worker(q):
    q.put("任务完成")

if __name__ == "__main__":
    queue = multiprocessing.Queue()
    process = multiprocessing.Process(target=worker, args=(queue,))
    process.start()
    process.join()

    # 从队列中获取结果
    result = queue.get()
    print(result)

在这个例子中,进程 worker 将结果放入队列中,主进程通过队列获取该结果。


3. 异步编程

异步编程是一种非阻塞的并发编程方式,适合 I/O 密集型任务。异步编程的核心思想是当一个任务等待 I/O 操作时,其他任务可以继续执行,从而避免阻塞。

3.1 使用 asyncio 模块

Python 的 asyncio 模块用于编写异步程序,通过 asyncawait 关键字定义异步函数。

示例:简单的异步函数

import asyncio

async def worker(name):
    print(f"任务 {name} 开始")
    await asyncio.sleep(2)
    print(f"任务 {name} 结束")

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

# 运行异步任务
asyncio.run(main())

在这个例子中,worker 是一个异步函数,它在执行 await asyncio.sleep(2) 时不会阻塞其他任务。

3.2 异步 I/O 操作

异步编程特别适合 I/O 密集型任务,比如网络请求、文件读写等。

示例:异步网络请求

import asyncio
import aiohttp

async def fetch(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            return await response.text()

async def main():
    urls = ['https://example.com', 'https://example.org']
    tasks = [fetch(url) for url in urls]
    results = await asyncio.gather(*tasks)
    for result in results:
        print(result)

# 运行异步任务
asyncio.run(main())

在这个示例中,使用 aiohttp 库进行异步网络请求,实现了非阻塞的 I/O 操作。


4. 协程与生成器

Python 的生成器(generator)和协程(coroutine)也是实现并发的工具之一。协程可以通过 yield 关键字暂停和恢复函数的执行。

4.1 协程示例

协程是一种比普通生成器更高级的函数控制机制,可以通过 yield 暂停执行,再通过 send() 恢复执行。

示例:协程

def coroutine_example():
    print("启动协程")
    result = yield
    print(f"接收到的值: {result}")

co = coroutine_example()
next(co)  # 启动协程
co.send(42)  # 向协程发送值

在这个例子中,协程通过 yield 暂停执行,再通过 send() 传递数据并恢复执行。


5. 小结

并发编程在提升程序性能和响应速度方面具有重要作用。Python 提供了多种并发编程模型,包括多线程、多进程和异步编程。选择哪种模型取决于任务的特点:对于 I/O 密集型任务,异步编程是首选;对于 CPU 密集型任务,多进程可能表现更好;多线程适合轻量级的并发任务。理解并掌握这些并发编程模型,能够显著提升 Python 程序的执行效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱技术的小伙子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值