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

在BLE设备连接场景中是否需要使用asyncio.Lock()?

要不要启用asyncio.Lock?给你捋清楚

首先明确:必须启用,原因如下:

你忽略了一个关键细节

你以为所有操作都在scan_and_connect()协程里,但disconnected_callback()是BLEak内部触发的——它运行在独立的任务上下文里,和你的scan_and_connect()是异步并发的。也就是说:

  • 当设备断开时,disconnected_callback()会偷偷修改connected_devices集合
  • 同时你的scan_and_connect()可能正在遍历、添加这个集合
  • 这俩操作撞在一起,轻则数据乱掉,重则直接抛出「集合迭代时被修改」的RuntimeError

什么时候必须用锁?

只要满足以下任一情况,锁就不能省:

  • disconnected_callback()里要改connected_devices
  • 除了scan_and_connect(),还有其他协程/回调会读写这个集合

正确的锁用法参考

  1. 先初始化全局锁:
    import asyncio
    connected_devices_lock = asyncio.Lock()
    
  2. 所有碰connected_devices的操作,都要套上锁:
    • 连接设备时加集合:
      async with connected_devices_lock:
          connected_devices.add(device_mac)
      
    • 断开回调里删元素:
      async def disconnected_callback(client):
          device_mac = client.address
          async with connected_devices_lock:
              if device_mac in connected_devices:
                  connected_devices.remove(device_mac)
      
    • 遍历集合时,最好先复制一份(避免持有锁太久阻塞其他操作):
      async with connected_devices_lock:
          # 复制成列表再遍历,锁可以早点释放
          current_online = list(connected_devices)
      for mac in current_online:
          # 做你的逻辑处理
      

为啥之前没出问题?

大概率是测试时设备断开次数少,并发冲突的概率低。但这是埋在代码里的隐患,等设备多了、运行时间长了,肯定会炸锅。

内容的提问来源于stack exchange,提问作者user173729

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 13:05:03