python知识
线程
问题:两个人同时改一个变量
# 一个银行账户
balance = 100
# 取款函数
def withdraw(amount):
global balance
if balance >= amount: # ① 检查够不够
balance -= amount # ② 扣钱
正常情况(一个人操作):
你取 60:① 检查 100 >= 60 ✓ → ② balance=40 → 余额 40
出问题的情况(两个人同时操作):
线程A(取60) 线程B(取80)
① 检查 100>=60 ✓
① 检查 100>=80 ✓ ← B 看到的还是 100!
② balance = 100-60 = 40 ← A 改了
② balance = 100-80 = 20 ← B 用旧值覆盖了 A 的修改
最终余额 20,但明明取了 60+80=140,应该报错的。这就是多线程同时改一个变量的风险。
解决方案:锁(Lock)
锁就像厕所门,一次只能一个人进去。
lock = Lock() # 创建一把锁
balance = 100
def withdraw(amount):
global balance
lock.acquire() # 🔒 锁门(别人等着)
if balance >= amount:
balance -= amount
lock.release() # 🔓 开门(下一个人可以进)
加锁后的执行:
线程A 线程B
lock.acquire() 🔒 拿到锁
① 检查 100>=60 ✓ lock.acquire() 🚫 等...(A 占着)
② balance=40 🚫 还在等...
lock.release() 🔓 释放锁
lock.acquire() 🔒 拿到锁了!
① 检查 40>=80 ✗ 钱不够,不扣
lock.release() 🔓
B 现在看到的是 A 改完后的 40,正确拒绝。
with lock: 是什么?
就是上面 acquire/release 的自动版本:
# 手动版(繁琐,容易忘 release)
lock.acquire()
# ... 你的代码 ...
lock.release()
# with 版(自动,永远不会忘释放)
with lock:
# ... 你的代码 ...
with 保证:不管代码块里发生了什么(正常结束、提前 return、甚至报错崩溃),锁一定会被释放。
对比:
# 手动版 — 如果这行报错,下面 release 永远不执行 → 死锁
lock.acquire()
data = 1 / 0 # 报错!
lock.release() # 永远跑不到这行 ← BUG
# with 版 — 报错也会自动释放
with lock:
data = 1 / 0 # 报错!但 with 自动调 release(),锁不会死
回到你的代码
def new_round(self):
with self.lock: # 🔒 锁住
self.pending.clear() # 清空旧数据
self.running = True # 标记运行中
self.round += 1 # 轮号+1
return self.round # 返回新轮号
# 🔓 with 结束,自动解锁
这三步(清空 + 标记 + 递增)必须一次做完,中间不能被打断。如果不用 with:
线程A(new_round) 线程B(append)
pending.clear() ✅
round_id=3 ≠ self.round=2 → 不写入 ✅ 正常
running = True ✅
round_id=3 ≠ self.round=2 → 不写入 ✅ 正常
self.round += 1 → round=3
round_id=3 == self.round=3 → 写入!❌
(但 pending 已经在上一行被 clear 了,
这一瞬间 running=True 但 pending=空)
加了 with,B 的 append 要么在 A 完全改完之前执行(看到旧 round),要么在完全改完之后执行(看到新 round),不会看到”改了一半”的中间状态。
- Title: python知识
- Author: 明廷盛
- Created at : 2026-07-25 07:56:17
- Updated at : 2026-07-25 15:51:00
- Link: https://blog.20040424.xyz/2026/07/25/⏸️VibeCoding/python知识/
- License: All Rights Reserved © 明廷盛