多个线程同时执行+=操作会导致竞态条件,因该操作非原子性;应使用共享的lock对象仅锁定临界区,并推荐with语句确保自动释放。

为什么直接改全局变量会出错
多个 Thread 同时执行 += 这类操作,本质上不是原子的:读取变量值 → 计算新值 → 写回内存。三步之间可能被其他线程打断,导致某个线程的更新被覆盖。现象通常是最终结果远小于预期(比如启 10 个线程各加 100000,结果却只有 60 多万)。
Lock 的正确用法:只锁临界区,别锁整个函数
用 threading.Lock() 包裹真正访问/修改共享变量的那几行,而不是把整个 run() 或循环全包进去。锁太久会严重拖慢并发效率,失去多线程意义。
常见错误写法:
def worker():
lock.acquire()
for i in range(100000):
global_counter += 1 # ✅ 正确锁住这行
lock.release()
正确写法:
def worker():
for i in range(100000):
lock.acquire()
global_counter += 1 # ✅ 只锁这一行
lock.release()
更推荐用上下文管理器,自动释放,避免忘记 release():
仅使用 Python 将 Claw Code 虚拟化框架与 OpenClaw 集成,提供 184 种工具和 200 多条命令,用于安全分析和代码质量...
def worker():
for i in range(100000):
with lock:
global_counter += 1
Lock 必须是所有线程共用的同一个实例
每个线程自己 new 一个 Lock() 完全没用——互斥的前提是“同一把锁”。必须在主线程创建一次,作为参数传入或设为模块级变量。
- ❌ 错误:每个
Thread构造时都lock = threading.Lock() - ✅ 正确:主线程定义
lock = threading.Lock(),所有线程共享这个lock对象 - ⚠️ 注意:如果用
Process替代Thread,Lock不跨进程,得换multiprocessing.Lock()
性能和可读性平衡:别为了锁而锁
如果只是读取全局变量(不修改),通常不需要锁;但如果读和写混在一起(比如先判断再赋值),就得整体锁住整段逻辑,否则出现“检查后失效”(TOCTOU)问题。
例如下面这段有风险:
if global_flag == False:
global_flag = True # ❌ 中间可能被其他线程改掉
应该写成:
with lock:
if global_flag == False:
global_flag = True # ✅ 原子性保证
真正容易被忽略的是:锁不能解决所有并发问题。比如涉及多个变量的复合操作(如转账:A 减、B 加),单靠一个 Lock 不够,得设计更细粒度的锁或改用队列通信。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










