# 并发处理机制 ## 🎯 学习目标 通过本章学习,您将能够: - 理解多人聊天中的并发处理挑战和解决方案 - 掌握线程安全和资源共享的核心技术 - 学会设计高并发的聊天服务器架构 - 在Chat-Room项目中实现稳定的并发处理系统 ## ⚡ 并发处理架构 ### 并发挑战分析 ```mermaid graph TB subgraph "并发挑战" A[资源竞争
Resource Competition] --> A1[共享数据访问] A --> A2[内存一致性] A --> A3[死锁风险] B[性能瓶颈
Performance Bottleneck] --> B1[线程创建开销] B --> B2[上下文切换] B --> B3[锁竞争] C[数据一致性
Data Consistency] --> C1[读写冲突] C --> C2[事务完整性] C --> C3[缓存同步] D[错误处理
Error Handling] --> D1[异常传播] D --> D2[资源泄漏] D --> D3[故障恢复] end style A fill:#f8d7da style B fill:#fff3cd style C fill:#d4edda style D fill:#d1ecf1 ``` ### 并发处理策略 ```mermaid graph LR subgraph "Chat-Room并发架构" A[连接管理器
Connection Manager] --> B[线程池
Thread Pool] B --> C[任务队列
Task Queue] C --> D[工作线程
Worker Threads] D --> E[消息处理
Message Processing] D --> F[数据库操作
Database Operations] D --> G[文件处理
File Processing] H[同步机制
Synchronization] --> H1[读写锁
RWLock] H --> H2[条件变量
Condition] H --> H3[信号量
Semaphore] I[资源管理
Resource Management] --> I1[连接池
Connection Pool] I --> I2[内存管理
Memory Management] I --> I3[缓存系统
Cache System] end style A fill:#e8f5e8 style H fill:#fff3cd style I fill:#f8d7da ``` ## 🔒 线程安全实现 ### 线程安全的数据结构 ```python # server/concurrent/thread_safe_structures.py - 线程安全数据结构 import threading import time from typing import Dict, List, Set, Any, Optional, Callable from collections import defaultdict, deque import weakref class ThreadSafeDict: """ 线程安全字典 提供线程安全的字典操作,支持读写锁优化 """ def __init__(self): self._data: Dict[Any, Any] = {} self._lock = threading.RWLock() # 读写锁 def get(self, key: Any, default: Any = None) -> Any: """线程安全的获取操作""" with self._lock.read_lock(): return self._data.get(key, default) def set(self, key: Any, value: Any): """线程安全的设置操作""" with self._lock.write_lock(): self._data[key] = value def delete(self, key: Any) -> bool: """线程安全的删除操作""" with self._lock.write_lock(): if key in self._data: del self._data[key] return True return False def update(self, other: Dict[Any, Any]): """线程安全的批量更新""" with self._lock.write_lock(): self._data.update(other) def keys(self) -> List[Any]: """获取所有键的快照""" with self._lock.read_lock(): return list(self._data.keys()) def values(self) -> List[Any]: """获取所有值的快照""" with self._lock.read_lock(): return list(self._data.values()) def items(self) -> List[tuple]: """获取所有项的快照""" with self._lock.read_lock(): return list(self._data.items()) def __len__(self) -> int: """获取字典长度""" with self._lock.read_lock(): return len(self._data) def __contains__(self, key: Any) -> bool: """检查键是否存在""" with self._lock.read_lock(): return key in self._data class ThreadSafeSet: """ 线程安全集合 提供线程安全的集合操作 """ def __init__(self, initial_data: Set[Any] = None): self._data: Set[Any] = set(initial_data) if initial_data else set() self._lock = threading.RLock() def add(self, item: Any): """添加元素""" with self._lock: self._data.add(item) def remove(self, item: Any) -> bool: """移除元素""" with self._lock: if item in self._data: self._data.remove(item) return True return False def discard(self, item: Any): """安全移除元素(不存在时不报错)""" with self._lock: self._data.discard(item) def update(self, other: Set[Any]): """批量添加元素""" with self._lock: self._data.update(other) def copy(self) -> Set[Any]: """获取集合的副本""" with self._lock: return self._data.copy() def __len__(self) -> int: """获取集合大小""" with self._lock: return len(self._data) def __contains__(self, item: Any) -> bool: """检查元素是否存在""" with self._lock: return item in self._data class ThreadSafeCounter: """ 线程安全计数器 提供原子性的计数操作 """ def __init__(self, initial_value: int = 0): self._value = initial_value self._lock = threading.Lock() def increment(self, delta: int = 1) -> int: """原子性递增""" with self._lock: self._value += delta return self._value def decrement(self, delta: int = 1) -> int: """原子性递减""" with self._lock: self._value -= delta return self._value def get(self) -> int: """获取当前值""" with self._lock: return self._value def set(self, value: int) -> int: """设置值""" with self._lock: old_value = self._value self._value = value return old_value def compare_and_swap(self, expected: int, new_value: int) -> bool: """比较并交换(CAS操作)""" with self._lock: if self._value == expected: self._value = new_value return True return False class EventBus: """ 线程安全事件总线 用于组件间的解耦通信 """ def __init__(self): self._subscribers: Dict[str, List[Callable]] = defaultdict(list) self._lock = threading.RLock() def subscribe(self, event_type: str, callback: Callable): """订阅事件""" with self._lock: self._subscribers[event_type].append(callback) def unsubscribe(self, event_type: str, callback: Callable): """取消订阅""" with self._lock: if event_type in self._subscribers: try: self._subscribers[event_type].remove(callback) except ValueError: pass def publish(self, event_type: str, *args, **kwargs): """发布事件""" # 获取订阅者列表的副本,避免在回调过程中修改 with self._lock: callbacks = self._subscribers[event_type].copy() # 异步调用回调函数 for callback in callbacks: try: # 在新线程中执行回调,避免阻塞 threading.Thread( target=callback, args=args, kwargs=kwargs, daemon=True ).start() except Exception as e: print(f"事件回调执行失败: {e}") # 读写锁实现 class RWLock: """ 读写锁实现 允许多个读者同时访问,但写者独占访问 """ def __init__(self): self._read_ready = threading.Condition(threading.RLock()) self._readers = 0 def read_lock(self): """获取读锁""" return self._ReadLock(self) def write_lock(self): """获取写锁""" return self._WriteLock(self) def _acquire_read(self): """获取读锁""" with self._read_ready: self._readers += 1 def _release_read(self): """释放读锁""" with self._read_ready: self._readers -= 1 if self._readers == 0: self._read_ready.notifyAll() def _acquire_write(self): """获取写锁""" with self._read_ready: while self._readers > 0: self._read_ready.wait() def _release_write(self): """释放写锁""" with self._read_ready: self._read_ready.notifyAll() class _ReadLock: def __init__(self, rwlock): self._rwlock = rwlock def __enter__(self): self._rwlock._acquire_read() def __exit__(self, exc_type, exc_val, exc_tb): self._rwlock._release_read() class _WriteLock: def __init__(self, rwlock): self._rwlock = rwlock def __enter__(self): self._rwlock._acquire_write() def __exit__(self, exc_type, exc_val, exc_tb): self._rwlock._release_write() ## 🏭 线程池管理 ### 智能线程池实现 ```python # server/concurrent/thread_pool.py - 线程池管理 import threading import queue import time from typing import Callable, Any, Optional, List from dataclasses import dataclass from enum import Enum import weakref class TaskPriority(Enum): """任务优先级""" LOW = 3 NORMAL = 2 HIGH = 1 URGENT = 0 @dataclass class Task: """任务对象""" func: Callable args: tuple kwargs: dict priority: TaskPriority = TaskPriority.NORMAL callback: Optional[Callable] = None error_callback: Optional[Callable] = None timeout: Optional[float] = None created_at: float = None def __post_init__(self): if self.created_at is None: self.created_at = time.time() def __lt__(self, other): """用于优先级队列排序""" return self.priority.value < other.priority.value class ThreadPoolExecutor: """ 智能线程池执行器 特性: 1. 动态线程数调整 2. 任务优先级支持 3. 超时处理 4. 性能监控 5. 优雅关闭 """ def __init__(self, min_threads: int = 2, max_threads: int = 20, keep_alive_time: float = 60.0, queue_size: int = 1000): self.min_threads = min_threads self.max_threads = max_threads self.keep_alive_time = keep_alive_time # 任务队列 self.task_queue = queue.PriorityQueue(maxsize=queue_size) # 线程管理 self.threads: List[threading.Thread] = [] self.active_threads = ThreadSafeCounter() self.idle_threads = ThreadSafeCounter() # 控制标志 self.shutdown = False self.shutdown_lock = threading.Lock() # 统计信息 self.stats = { 'tasks_submitted': ThreadSafeCounter(), 'tasks_completed': ThreadSafeCounter(), 'tasks_failed': ThreadSafeCounter(), 'total_execution_time': 0.0, 'peak_threads': ThreadSafeCounter() } # 监控线程 self.monitor_thread = None # 初始化核心线程 self._create_core_threads() self._start_monitor() def submit(self, func: Callable, *args, priority: TaskPriority = TaskPriority.NORMAL, callback: Callable = None, error_callback: Callable = None, timeout: float = None, **kwargs) -> bool: """ 提交任务到线程池 Args: func: 要执行的函数 *args: 函数参数 priority: 任务优先级 callback: 成功回调 error_callback: 错误回调 timeout: 超时时间 ## 📖 导航 ⬅️ **上一节:** [Message Routing](message-routing.md) ➡️ **下一节:** [State Management](state-management.md) 📚 **返回:** [第9章:多人聊天](README.md) 🏠 **主页:** [学习路径总览](../README.md) **kwargs: 函数关键字参数 Returns: 是否成功提交 """ if self.shutdown: return False task = Task( func=func, args=args, kwargs=kwargs, priority=priority, callback=callback, error_callback=error_callback, timeout=timeout ) try: # 使用优先级作为排序键 self.task_queue.put((priority.value, task), timeout=1.0) self.stats['tasks_submitted'].increment() # 检查是否需要创建新线程 self._maybe_create_thread() return True except queue.Full: print("任务队列已满,无法提交任务") return False def _create_core_threads(self): """创建核心线程""" for i in range(self.min_threads): self._create_worker_thread(is_core=True) def _create_worker_thread(self, is_core: bool = False) -> threading.Thread: """创建工作线程""" thread = threading.Thread( target=self._worker_loop, args=(is_core,), name=f"ThreadPool-Worker-{len(self.threads)}", daemon=True ) self.threads.append(thread) self.active_threads.increment() # 更新峰值线程数 current_count = len(self.threads) peak_count = self.stats['peak_threads'].get() if current_count > peak_count: self.stats['peak_threads'].set(current_count) thread.start() return thread def _worker_loop(self, is_core: bool): """工作线程主循环""" last_task_time = time.time() while not self.shutdown: try: # 获取任务 timeout = None if is_core else self.keep_alive_time priority, task = self.task_queue.get(timeout=timeout) if task is None: # 关闭信号 break last_task_time = time.time() self.idle_threads.decrement() # 执行任务 self._execute_task(task) self.idle_threads.increment() self.task_queue.task_done() except queue.Empty: # 非核心线程超时退出 if not is_core: current_time = time.time() if current_time - last_task_time > self.keep_alive_time: break except Exception as e: print(f"工作线程异常: {e}") # 线程退出清理 self.active_threads.decrement() if not is_core: self.idle_threads.decrement() def _execute_task(self, task: Task): """执行单个任务""" start_time = time.time() try: # 检查任务是否超时 if task.timeout and (start_time - task.created_at) > task.timeout: raise TimeoutError(f"任务超时: {task.timeout}秒") # 执行任务 result = task.func(*task.args, **task.kwargs) # 执行成功回调 if task.callback: try: task.callback(result) except Exception as e: print(f"任务回调执行失败: {e}") self.stats['tasks_completed'].increment() except Exception as e: # 执行错误回调 if task.error_callback: try: task.error_callback(e) except Exception as callback_error: print(f"错误回调执行失败: {callback_error}") else: print(f"任务执行失败: {e}") self.stats['tasks_failed'].increment() finally: # 更新执行时间统计 execution_time = time.time() - start_time self.stats['total_execution_time'] += execution_time def _maybe_create_thread(self): """根据负载情况决定是否创建新线程""" if self.shutdown: return current_threads = len(self.threads) idle_count = self.idle_threads.get() queue_size = self.task_queue.qsize() # 如果队列有积压且空闲线程不足,创建新线程 if (queue_size > 0 and idle_count == 0 and current_threads < self.max_threads): self._create_worker_thread(is_core=False) def _start_monitor(self): """启动监控线程""" self.monitor_thread = threading.Thread( target=self._monitor_loop, name="ThreadPool-Monitor", daemon=True ) self.monitor_thread.start() def _monitor_loop(self): """监控线程主循环""" while not self.shutdown: try: time.sleep(30) # 每30秒检查一次 # 清理空闲线程 self._cleanup_idle_threads() # 打印统计信息 self._print_stats() except Exception as e: print(f"监控线程异常: {e}") def _cleanup_idle_threads(self): """清理过多的空闲线程""" current_threads = len(self.threads) if current_threads <= self.min_threads: return # 移除已结束的线程 self.threads = [t for t in self.threads if t.is_alive()] def _print_stats(self): """打印统计信息""" stats = self.get_stats() print(f"线程池状态: 活跃线程={stats['active_threads']}, " f"空闲线程={stats['idle_threads']}, " f"队列大小={stats['queue_size']}, " f"完成任务={stats['completed_tasks']}") def get_stats(self) -> dict: """获取线程池统计信息""" return { 'active_threads': self.active_threads.get(), 'idle_threads': self.idle_threads.get(), 'total_threads': len(self.threads), 'queue_size': self.task_queue.qsize(), 'submitted_tasks': self.stats['tasks_submitted'].get(), 'completed_tasks': self.stats['tasks_completed'].get(), 'failed_tasks': self.stats['tasks_failed'].get(), 'peak_threads': self.stats['peak_threads'].get(), 'total_execution_time': self.stats['total_execution_time'] } def shutdown_gracefully(self, timeout: float = 30.0): """优雅关闭线程池""" with self.shutdown_lock: if self.shutdown: return self.shutdown = True print("开始关闭线程池...") # 等待队列中的任务完成 try: self.task_queue.join() except: pass # 发送关闭信号给所有线程 for _ in self.threads: try: self.task_queue.put((0, None), timeout=1.0) except queue.Full: break # 等待线程结束 start_time = time.time() for thread in self.threads: remaining_time = timeout - (time.time() - start_time) if remaining_time > 0: thread.join(timeout=remaining_time) print("线程池已关闭") # 使用示例 def demo_thread_pool(): """线程池演示""" def sample_task(task_id: int, duration: float): """示例任务""" print(f"任务 {task_id} 开始执行") time.sleep(duration) print(f"任务 {task_id} 执行完成") return f"任务 {task_id} 结果" def task_callback(result): """任务完成回调""" print(f"任务完成回调: {result}") def error_callback(error): """任务错误回调""" print(f"任务错误回调: {error}") # 创建线程池 pool = ThreadPoolExecutor(min_threads=2, max_threads=5) print("=== 线程池演示 ===") # 提交不同优先级的任务 for i in range(10): priority = TaskPriority.HIGH if i < 3 else TaskPriority.NORMAL pool.submit( sample_task, i, 0.5, priority=priority, callback=task_callback, error_callback=error_callback ) # 等待一段时间 time.sleep(3) # 查看统计信息 stats = pool.get_stats() print(f"线程池统计: {stats}") # 关闭线程池 pool.shutdown_gracefully() # 为threading模块添加读写锁 threading.RWLock = RWLock ```