线程环境下请求计数器无法递增问题排查
问题:请求计数器始终显示1
需求是每次发送请求后打印已发送请求的总数,但运行时计数器一直停留在1。
原代码
def send(): while True: total = 0 req = requests.get(url) if req.status_code == 403: logging.info("Unable to fufill request!") else: pass total = total + 1 logging.info(f"Request No. {total} sent") for _ in range(int(amount)): t = threading.Thread(target=send) t.start()
预期输出
Request No. 1 sent Request No. 2 sent ...
实际输出
Request No. 1 sent Request No. 1 sent ...
问题原因
- 变量作用域错误:
total被定义在while True循环内部,每次循环都会重新初始化total = 0,导致每次自增后结果永远是1,无法累计计数。 - 多线程竞争隐患:即使把
total移到全局,多个线程同时修改该变量会出现计数混乱——线程间的数值修改不是原子操作,可能出现覆盖问题。
修复代码
通过全局变量配合线程锁保证计数准确性,同时调整变量作用域:
import threading import requests import logging # 全局计数器与线程锁 total = 0 lock = threading.Lock() def send(): global total # 若无需无限发送请求,可移除while True循环 while True: req = requests.get(url) if req.status_code == 403: logging.info("无法完成请求!") else: # 加锁确保计数器修改的原子性 with lock: total += 1 logging.info(f"已发送请求 No. {total}") amount = 5 # 示例线程数量 for _ in range(int(amount)): t = threading.Thread(target=send) t.start()
额外说明
- 原代码中
while True会让每个线程无限发送请求,若实际需求是总共发送amount次请求,可移除while True,让每个线程仅执行一次请求逻辑。 - 使用
with lock可自动完成锁的获取与释放,避免手动操作锁引发的死锁问题。
内容的提问来源于stack exchange,提问作者Lamp
相关产品推荐
相关产品推荐

