本文目录导读:

- 线程安全 - threading模块
- 使用条件变量(Condition)
- 使用Queue实现线程安全
- 使用Event实现线程协调
- 使用Semaphore控制并发数量
- 进程安全 - multiprocessing模块
- 使用全局解释器锁(GIL)特性
- 使用futures模块
- 原子操作示例
- 并发安全的最佳实践
我来详细介绍Python中保障并发安全的常用方法和最佳实践。
线程安全 - threading模块
使用Lock(锁)
import threading
import time
class BankAccount:
def __init__(self):
self.balance = 0
self.lock = threading.Lock() # 创建锁
def deposit(self, amount):
with self.lock: # 自动获取和释放锁
current = self.balance
time.sleep(0.1) # 模拟IO操作
self.balance = current + amount
print(f"{threading.current_thread().name}: +${amount} -> {self.balance}")
def withdraw(self, amount):
with self.lock:
if self.balance >= amount:
current = self.balance
time.sleep(0.1)
self.balance = current - amount
print(f"{threading.current_thread().name}: -${amount} -> {self.balance}")
else:
print(f"{threading.current_thread().name}: 余额不足")
# 测试
account = BankAccount()
threads = []
for i in range(5):
t1 = threading.Thread(target=account.deposit, args=(100,), name=f"存款线程-{i}")
t2 = threading.Thread(target=account.withdraw, args=(50,), name=f"取款线程-{i}")
threads.extend([t1, t2])
for t in threads:
t.start()
for t in threads:
t.join()
print(f"最终余额: ${account.balance}")
使用RLock(可重入锁)
class Counter:
def __init__(self):
self.count = 0
self.lock = threading.RLock() # 可重入锁
def increment(self):
with self.lock:
self.count += 1
# 可以再次获取同一个锁(可重入)
self.do_something_else()
def do_something_else(self):
with self.lock: # 不会死锁
pass
def get_count(self):
with self.lock:
return self.count
使用条件变量(Condition)
import threading
class BoundedBuffer:
def __init__(self, max_size=5):
self.buffer = []
self.max_size = max_size
self.lock = threading.Lock()
self.not_full = threading.Condition(self.lock)
self.not_empty = threading.Condition(self.lock)
def put(self, item):
with self.not_full:
while len(self.buffer) >= self.max_size:
print(f"缓冲区已满,生产者{threading.current_thread().name}等待...")
self.not_full.wait()
self.buffer.append(item)
print(f"生产者{threading.current_thread().name}放入{item}, 缓冲区大小:{len(self.buffer)}")
self.not_empty.notify() # 通知消费者
def get(self):
with self.not_empty:
while len(self.buffer) == 0:
print(f"缓冲区为空,消费者{threading.current_thread().name}等待...")
self.not_empty.wait()
item = self.buffer.pop(0)
print(f"消费者{threading.current_thread().name}取出{item}, 缓冲区大小:{len(self.buffer)}")
self.not_full.notify() # 通知生产者
return item
# 测试
buffer = BoundedBuffer()
def producer():
for i in range(10):
buffer.put(f"产品-{i}")
def consumer():
for _ in range(10):
buffer.get()
threads = []
for i in range(2):
t1 = threading.Thread(target=producer, name=f"P-{i}")
t2 = threading.Thread(target=consumer, name=f"C-{i}")
threads.extend([t1, t2])
for t in threads:
t.start()
for t in threads:
t.join()
使用Queue实现线程安全
from queue import Queue
import queue # 注意导入的是queue模块
def worker_task(task_queue, result_queue, worker_id):
while True:
try:
# 非阻塞方式获取任务
task = task_queue.get_nowait()
# 处理任务
result = task * 2
result_queue.put(result)
print(f"工作者{worker_id}处理: {task} -> {result}")
task_queue.task_done()
except queue.Empty:
break
# 创建队列
task_queue = Queue()
result_queue = Queue()
# 添加任务
for i in range(20):
task_queue.put(i)
# 创建工作者线程
workers = []
for i in range(4):
w = threading.Thread(target=worker_task, args=(task_queue, result_queue, i))
workers.append(w)
w.start()
# 等待所有任务完成
task_queue.join()
# 收集结果
results = []
while not result_queue.empty():
results.append(result_queue.get())
print(f"所有结果: {sorted(results)}")
使用Event实现线程协调
import threading
import time
class DataProcessor:
def __init__(self):
self.data = None
self.data_ready = threading.Event()
self.data_processed = threading.Event()
def producer(self):
print("生产者: 准备数据...")
time.sleep(2)
self.data = {"name": "Python并发", "value": 100}
print("生产者: 数据准备完毕")
self.data_ready.set() # 通知消费者
self.data_processed.wait() # 等待消费者处理完成
print("生产者: 确认消费者已处理")
def consumer(self):
print("消费者: 等待数据...")
self.data_ready.wait() # 等待生产者
print(f"消费者: 处理数据 {self.data}")
time.sleep(1)
self.data["processed"] = True
print("消费者: 处理完成")
self.data_processed.set() # 通知生产者
# 测试
processor = DataProcessor()
t1 = threading.Thread(target=processor.producer)
t2 = threading.Thread(target=processor.consumer)
t1.start()
t2.start()
t1.join()
t2.join()
使用Semaphore控制并发数量
import threading
import time
class WebScraper:
def __init__(self, max_concurrent=3):
self.semaphore = threading.Semaphore(max_concurrent)
def scrape_url(self, url, scraper_id):
with self.semaphore:
print(f"爬虫{scraper_id}: 开始爬取 {url}")
time.sleep(2) # 模拟网络请求
print(f"爬虫{scraper_id}: 完成爬取 {url}")
# 测试
scraper = WebScraper(max_concurrent=3)
urls = [f"http://example.com/page/{i}" for i in range(10)]
threads = []
for i, url in enumerate(urls):
t = threading.Thread(target=scraper.scrape_url, args=(url, i))
threads.append(t)
t.start()
for t in threads:
t.join()
进程安全 - multiprocessing模块
from multiprocessing import Process, Value, Array, Lock
import time
class SharedCounter:
def __init__(self):
self.count = Value('i', 0) # 共享整数
self.lock = Lock()
def increment(self, amount):
with self.lock:
self.count.value += amount
print(f"进程{threading.current_thread().name}: 计数 {self.count.value}")
time.sleep(0.1)
def worker(counter, amount):
for _ in range(10):
counter.increment(amount)
# 测试
counter = SharedCounter()
processes = []
for i in range(3):
p = Process(target=worker, args=(counter, 1))
processes.append(p)
p.start()
for p in processes:
p.join()
print(f"最终计数: {counter.count.value}")
使用全局解释器锁(GIL)特性
import threading
import time
# CPU密集型任务 - 受GIL影响
class CPUTask:
def compute(self):
total = 0
for _ in range(50000000):
total += 1
return total
# 使用多进程处理CPU密集型任务
def cpu_intensive_task(name):
total = 0
for i in range(10000000):
total += i
return f"{name}: {total}"
# 最佳实践:根据不同场景选择并发模型
def process_by_type(task_type, data):
if task_type == "IO":
# IO密集型任务使用多线程
threads = []
for item in data:
t = threading.Thread(target=handle_io, args=(item,))
threads.append(t)
t.start()
for t in threads:
t.join()
else:
# CPU密集型任务使用多进程
from concurrent.futures import ProcessPoolExecutor
with ProcessPoolExecutor() as executor:
results = executor.map(handle_cpu, data)
使用futures模块
from concurrent.futures import ThreadPoolExecutor, as_completed
import threading
def thread_safe_operation(value, lock):
with lock:
print(f"处理值: {value}")
return value * 2
lock = threading.Lock()
values = list(range(20))
# 使用线程池
with ThreadPoolExecutor(max_workers=5) as executor:
futures = {executor.submit(thread_safe_operation, v, lock): v for v in values}
for future in as_completed(futures):
result = future.result()
print(f"结果: {result}")
原子操作示例
import threading
class AtomicCounter:
def __init__(self):
self._lock = threading.Lock()
self._count = 0
def increment(self):
# 使用原子操作(通过锁实现)
with self._lock:
self._count += 1
@property
def count(self):
with self._lock:
return self._count
# 虽然Python有GIL,但多线程下仍需注意
class NonSafeCounter:
def __init__(self):
self.count = 0
def increment(self):
# 非原子操作,可能出问题
count = self.count
count += 1
self.count = count # 这里可能被其他线程打断
并发安全的最佳实践
import threading
from contextlib import contextmanager
class ConnectionPool:
def __init__(self, max_connections=5):
self._connections = []
self._max = max_connections
self._lock = threading.Lock()
self._cond = threading.Condition(self._lock)
@contextmanager
def get_connection(self):
with self._cond:
while len(self._connections) >= self._max:
self._cond.wait()
conn = self._create_connection()
self._connections.append(conn)
try:
yield conn
finally:
with self._cond:
self._connections.remove(conn)
self._cond.notify()
def _create_connection(self):
return "Connection-" + str(threading.current_thread().ident)
# 使用示例
pool = ConnectionPool(max_connections=3)
def use_connection(thread_id):
with pool.get_connection() as conn:
print(f"线程{thread_id}: 使用连接 {conn}")
import time
time.sleep(0.5)
threads = []
for i in range(10):
t = threading.Thread(target=use_connection, args=(i,))
threads.append(t)
t.start()
for t in threads:
t.join()
-
选择正确的锁类型:
Lock: 基本互斥锁RLock: 可重入锁,适合递归调用Semaphore: 控制并发数量Event: 线程间信号通知Condition: 条件变量,复杂协调
-
安全准则:
- 尽量使用
with语句自动管理锁 - 避免死锁(注意锁的顺序)
- 最小化锁的持有时间
- 考虑使用
queue.Queue代替自定义同步
- 尽量使用
-
性能考虑:
- IO密集型任务使用多线程
- CPU密集型任务使用多进程
- 使用线程池/进程池管理资源
-
调试技巧:
- 使用
logging而非print避免输出混合 - 添加适当的错误处理
- 使用
timeout参数避免无限等待
- 使用
这些示例涵盖了Python并发安全的主要场景和最佳实践,根据具体需求选择合适的同步机制是关键。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播