You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 07:12:48