Python并发编程:多线程与多进程实战指南

Python并发编程:多线程与多进程实战指南

在Python中处理大量任务时,并发编程能够显著提升程序性能。本文将详细介绍Python中的多线程和多进程技术,帮助你掌握并发编程的核心知识。

一、并发编程基础

1. 什么是并发?

并发是指程序同时处理多个任务的能力。在单核CPU上,这是通过时间片轮转实现的,让不同任务快速切换执行。

2. 多线程 vs 多进程

  • 多线程:共享内存空间,上下文切换快,但存在全局解释器锁(GIL)限制
    • 多进程:独立内存空间,不受GIL限制,但上下文切换开销大

二、多线程实现

1. 创建线程

python 复制代码
  • import threading
  • def worker():
bash 复制代码
print('Thread is working...')
bash 复制代码
# 创建线程
ini 复制代码
thread = threading.Thread(target=worker)
arduino 复制代码
thread.start()
arduino 复制代码
thread.join()
go 复制代码
```
shell 复制代码
### 2. 线程同步
go 复制代码
```python
javascript 复制代码
from threading import Lock, Semaphore
ini 复制代码
lock = Lock()
ini 复制代码
semaphore = Semaphore(3)  # 限制同时访问数量
go 复制代码
```
shell 复制代码
### 3. 线程安全
go 复制代码
```python
bash 复制代码
# 使用 Lock
csharp 复制代码
with lock:
bash 复制代码
    # 线程安全代码
bash 复制代码
    # 使用 Semaphore
markdown 复制代码
    semaphore.acquire()
bash 复制代码
    # 使用后释放
markdown 复制代码
    semaphore.release()
go 复制代码
    ```
bash 复制代码
    ## 三、多进程实现
bash 复制代码
    ### 1. 创建进程
go 复制代码
    ```python
arduino 复制代码
    from multiprocessing import Process
ruby 复制代码
    def worker_process():
bash 复制代码
        print('Process is working...')
bash 复制代码
        # 创建进程
ini 复制代码
        process = Process(target=worker_process)
arduino 复制代码
        process.start()
arduino 复制代码
        process.join()
go 复制代码
        ```
bash 复制代码
        ### 2. 进程间通信
go 复制代码
        ```python
javascript 复制代码
        from multiprocessing import Pipe, Queue
bash 复制代码
        # 使用 Pipe
ini 复制代码
        parent_conn, child_conn = Pipe()
arduino 复制代码
        parent_conn.send('hello')
ini 复制代码
        msg = child_conn.recv()
bash 复制代码
        # 使用 Queue
ini 复制代码
        queue = Queue()
arduino 复制代码
        queue.put('data')
ini 复制代码
        data = queue.get()
go 复制代码
        ```
bash 复制代码
        ### 3. 批量进程
go 复制代码
        ```python
javascript 复制代码
        from multiprocessing import Pool
python 复制代码
        def square(n):
kotlin 复制代码
            return n * n
ini 复制代码
            if __name__ == '__main__':
csharp 复制代码
                with Pool(4) as p:
go 复制代码
                        results = p.map(square, range(10))
scss 复制代码
                                print(results)
go 复制代码
                                ```
bash 复制代码
                                ## 四、实战案例
bash 复制代码
                                ### 1. 并发爬虫
go 复制代码
                                ```python
arduino 复制代码
                                import requests
javascript 复制代码
                                from concurrent.futures import ThreadPoolExecutor
python 复制代码
                                def fetch_url(url):
ini 复制代码
                                    response = requests.get(url)
arduino 复制代码
                                        return response.text
ini 复制代码
                                        urls = ['https://example.com', 'https://juejin.cn']
csharp 复制代码
                                        with ThreadPoolExecutor(max_workers=5) as executor:
ini 复制代码
                                            results = list(executor.map(fetch_url, urls))
scss 复制代码
                                                print(results)
go 复制代码
                                                ```
bash 复制代码
                                                ### 2. 并发计算
go 复制代码
                                                ```python
javascript 复制代码
                                                from multiprocessing import Pool
arduino 复制代码
                                                import time
python 复制代码
                                                def compute(n):
css 复制代码
                                                    time.sleep(1)
kotlin 复制代码
                                                        return n * n
ini 复制代码
                                                        if __name__ == '__main__':
csharp 复制代码
                                                            with Pool(4) as p:
go 复制代码
                                                                    results = p.map(compute, range(10))
scss 复制代码
                                                                        print(results)
go 复制代码
                                                                        ```
bash 复制代码
                                                                        ## 五、性能优化建议
markdown 复制代码
                                                                        1. **避免在I/O密集型任务中使用GIL**:使用多线程处理网络请求
markdown 复制代码
                                                                        2. **计算密集型任务使用多进程**:充分利用多核CPU
markdown 复制代码
                                                                        3. **合理设置线程/进程数量**:根据CPU核心数调整
markdown 复制代码
                                                                        4. **使用异步IO**:对于IO密集型任务,考虑asyncio
bash 复制代码
                                                                        ## 六、总结
markdown 复制代码
                                                                        并发编程能够显著提升Python程序的性能,但需要根据实际场景选择合适的技术:
markdown 复制代码
                                                                        - **I/O密集型任务**:优先考虑多线程
markdown 复制代码
                                                                        - **计算密集型任务**:优先考虑多进程
markdown 复制代码
                                                                        - **复杂场景**:考虑异步IO或混合方案
markdown 复制代码
                                                                        掌握这些技术,让你的Python程序更高效!
相关推荐
根目录下的猫3 小时前
虚拟机复制过来运行时:“虚拟机使用的此版本,VMware Workstation 不支持的硬件版本。”错误解决办法,亲测可用
linux·运维·服务器·后端
蜗牛互联网3 小时前
Java Agent 工具调用的 allowlist、参数校验与调用预算
java·开发语言·人工智能·后端·oracle
用户813267933253 小时前
行情数据晚到几秒,会让量化策略失去优势吗?从信号时间到回测偏差
后端·github·api
九零HTTP3 小时前
一次 TCP 连接的一生:从三次握手到四次挥手
后端
ZOnePieceC3 小时前
消息队列之Kafka
后端
yunwei373 小时前
eBPF 入门实践教程十七:编写 eBPF 程序统计随机/顺序磁盘 I/O
linux·后端·性能优化
花间相见3 小时前
【计算基础|网络07】HTTPS(下):ECDHE 握手与优化
后端
QuantiCore_IO3 小时前
从请求风暴到可维护的数据管道:量化系统为什么需要批量接口?
后端·github·api
136096757233 小时前
.env 的三个必查项
后端
长安米粒贵3 小时前
接口超时了,为什么重试反而把系统打垮?聊聊超时预算的 4 个误区
后端