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

Python多线程修改共享字典如何避免竞态条件问题

问题解答

1. 你的代码确实存在竞态条件

你之前看到的Python字典线程安全的结论,仅指单个读/写操作不会破坏字典的内部结构、不会出现半完成的赋值,但不能保证连续两个操作的原子性,中间仍然可能发生线程切换。

你代码里data['key'] = value赋值和下一行requests.get读取data是两个独立操作,组合起来不是原子的,完全可能在赋值完成后、发起请求前发生线程上下文切换。你举的场景完全成立:线程1赋值data['key'] = 1后切走,线程2把data['key']改成2,切回线程1发起请求时,读取到的key值就是2,和你预期的1不符。

2. 无锁高性能解决方案

完全不需要用锁,核心思路是避免多个线程修改共享的可变字典,最常用的实现方式开销极低,几乎不会影响并发效率:

方案:每次请求构造独立的临时字典

把固定键的字典作为只读模板,每次请求时和动态的key值合并成新字典,每个线程使用自己的临时字典,完全不存在共享修改,没有竞态问题:

import requests
from concurrent.futures import ThreadPoolExecutor

# 作为只读模板,不会被修改,线程安全
base_data = {'fixedKey': 'fixedValue', 'fixedKey2': 'fixedValue2'}
resultArray = []
threadPool = ThreadPoolExecutor(32)

def getUrl(url, value):
    # 每次构造新的临时字典,仅当前线程可见
    req_data = {**base_data, 'key': value}
    return requests.get(url, data=req_data).text

for i in range(100):
    resultArray.append(threadPool.submit(getUrl, 'https://google.com', i))

如果逻辑简单,也可以直接在传参时构造字典,不需要单独定义变量:

def getUrl(url, value):
    return requests.get(url, data={**base_data, 'key': value}).text

性能说明

字典解包合并的开销远低于锁的加解锁开销,而且不会阻塞其他线程的执行,完全不会影响预设的并发效率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 09:42:02