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程序更高效!