Python获取资源时如何等待且不阻塞线程?(连接池场景)
非阻塞式数据库连接池获取连接实现方案
你提到的问题核心是time.sleep(30)会阻塞线程,导致并发请求下线程资源被浪费,总等待时长无意义叠加。完全可以通过以下两种非阻塞方式实现等待逻辑,既保证等待期间线程/事件循环能处理其他任务,又能在连接释放时及时唤醒等待的请求:
一、多线程场景:用条件变量(Condition)替代sleep
在多线程环境下,使用线程库的Condition对象可以实现等待-唤醒机制,等待时会释放锁,让其他线程正常执行,避免无意义阻塞。
示例代码(Python):
import threading from typing import List class ConnectionPool: def __init__(self, max_connections: int = 5): self.max_connections = max_connections self.available_conns: List = [] self.condition = threading.Condition() # 初始化连接池 for _ in range(max_connections): self.available_conns.append(f"conn_{_}") def get_connection(self, timeout: int = 30) -> str | None: with self.condition: # 先尝试获取连接 if self.available_conns: return self.available_conns.pop() # 无可用连接时,等待指定时长,期间会释放锁 if self.condition.wait(timeout=timeout): # 被唤醒后再次尝试获取 if self.available_conns: return self.available_conns.pop() # 超时或唤醒后仍无连接,返回None return None def release_connection(self, conn: str): with self.condition: self.available_conns.append(conn) # 唤醒一个等待中的线程 self.condition.notify()
逻辑说明:
- 当调用
get_connection无可用连接时,condition.wait(timeout)会释放锁,当前线程进入等待状态,不会阻塞其他线程执行。 - 当其他线程调用
release_connection释放连接时,会调用condition.notify()唤醒一个等待的线程,该线程会重新尝试获取连接。 - 若等待超时,线程自动唤醒,再次尝试获取连接后失败则返回
None,总等待时长不会叠加。
二、异步IO场景:用asyncio的等待机制
如果你的项目是异步架构(比如用FastAPI、aiohttp),可以用asyncio的锁和超时等待实现非阻塞逻辑,不会阻塞事件循环。
示例代码(Python):
import asyncio from typing import List class AsyncConnectionPool: def __init__(self, max_connections: int = 5): self.max_connections = max_connections self.available_conns: List = [] self.lock = asyncio.Lock() # 初始化连接池 for _ in range(max_connections): self.available_conns.append(f"conn_{_}") async def get_connection(self, timeout: int = 30) -> str | None: try: # 设置超时等待 return await asyncio.wait_for(self._wait_and_get_conn(), timeout=timeout) except asyncio.TimeoutError: return None async def _wait_and_get_conn(self): async with self.lock: # 循环等待,直到有可用连接或超时 while not self.available_conns: # 释放锁,让其他协程可以操作连接池 await asyncio.sleep(0.1) # 短轮询避免空转 return self.available_conns.pop() async def release_connection(self, conn: str): async with self.lock: self.available_conns.append(conn)
逻辑说明:
asyncio.wait_for会在指定时长内等待协程完成,期间事件循环可以处理其他任务,不会被阻塞。- 短轮询的方式避免了空转,同时保证能及时响应连接释放的情况。
- 多个异步请求等待时,不会叠加等待时长,每个请求的超时时间都是独立的30秒。
核心优势对比
- 替代
time.sleep后,线程/事件循环在等待期间可以处理其他任务,大幅提升并发场景下的资源利用率。 - 等待时长是每个请求独立的30秒,不会出现多个请求阻塞时长叠加的问题。
- 连接释放时能及时唤醒等待的请求,减少无效等待时间。
内容的提问来源于stack exchange,提问作者Daniel Wu
相关产品推荐
相关产品推荐

