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

Python线程同步原语必要性验证:寻求竞态条件差异示例

多线程同步原语的差异示例

为什么你的初始代码没出现竞态

你之前的代码未触发竞态,是因为CPython的全局解释器锁(GIL)在执行简单字节码序列时不会频繁释放。counter += 1虽拆分为读取、计算、赋值三个非原子步骤,但如果线程在执行这几步时未被GIL调度打断,结果就会符合预期。要明显展示竞态,需让线程在修改共享变量时更易被切换。

无锁与加锁的对比示例

以下示例通过拆分递增操作并加入微小延迟,刻意触发线程切换,清晰展示同步原语的作用:

无锁版本(存在竞态)

from threading import Thread
import time

COUNT = 1000
NUM_THREADS = 10
counter = 0

def increment():
    global counter
    for _ in range(COUNT):
        # 显式拆分递增步骤,加入微小延迟触发GIL释放
        current = counter
        time.sleep(0.000001)
        counter = current + 1

threads = [Thread(target=increment) for _ in range(NUM_THREADS)]
for thread in threads:
    thread.start()
for thread in threads:
    thread.join()

print(f"无锁结果: {counter}")
print(f"预期结果: {COUNT * NUM_THREADS}")
print(f"差值: {counter - COUNT * NUM_THREADS}")

运行后,counter的值会远小于预期的10000——多个线程会同时读取到相同的current值,各自加1后赋值,导致大量递增操作被覆盖。

加锁版本(无竞态)

from threading import Thread, Lock
import time

COUNT = 1000
NUM_THREADS = 10
counter = 0
lock = Lock()

def increment():
    global counter
    for _ in range(COUNT):
        # 使用Lock确保临界区代码原子执行
        with lock:
            current = counter
            time.sleep(0.000001)
            counter = current + 1

threads = [Thread(target=increment) for _ in range(NUM_THREADS)]
for thread in threads:
    thread.start()
for thread in threads:
    thread.join()

print(f"加锁结果: {counter}")
print(f"预期结果: {COUNT * NUM_THREADS}")
print(f"差值: {counter - COUNT * NUM_THREADS}")

运行后,counter的值会严格等于10000——with lock块保证同一时间只有一个线程能执行临界区代码,彻底避免了数据竞争。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 07:52:52