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

为何添加thread.join()后Python多线程代码表现更安全?

问题描述

以下是一段Python多线程代码:

import threading

# Shared variable
shared_variable = 0
NUM_THREADS = 999
NUM_INCREMENT = 1_000_000


# Function to increment the shared variable
def increment():
    global shared_variable
    for _ in range(NUM_INCREMENT):
        shared_variable += 1


# Creating multiple threads to increment the shared variable concurrently
threads = []
for _ in range(NUM_THREADS):
    thread = threading.Thread(target=increment)
    threads.append(thread)

for thread in threads:
    thread.start()

for thread in threads:
    thread.join()

# Display the value of the shared variable after concurrent increments
print(
    f"The value of the shared variable is: {shared_variable}, expected : {NUM_THREADS * NUM_INCREMENT}"
)

当保留thread.join()代码块时,程序输出的共享变量值始终符合预期(即999 * 1000000);但注释掉该段代码后:

# for thread in threads:
#    thread.join()

会出现递增操作失效的情况(结果小于预期)。请问为何添加thread.join()后该多线程代码表现得更安全?


原因解析

核心原因和主线程的执行时机直接相关:

  • 不调用join()时,主线程启动所有子线程后,会立刻继续执行后续代码,直接跑到print语句输出结果,甚至可能在子线程还没完成全部递增操作前,主线程就已经结束了。Python中主线程结束时会强制终止所有仍在运行的子线程,这就导致大量递增操作根本没机会执行,最终结果自然远小于预期值。
  • 调用join()的作用就是让主线程进入阻塞状态,必须等所有子线程全部执行完毕后,才会继续执行后续的打印代码。这样所有子线程的递增操作都能完整执行,你看到的结果才会符合预期。

额外说明:这里要注意,shared_variable += 1本质上是线程不安全的操作——它拆分为读取当前值、加1、写入新值三个独立步骤,多线程并发时会出现竞态条件,导致值被覆盖。你这次测试中加join()后结果符合预期只是巧合,若线程调度时机特殊,即使加了join(),理论上还是可能出现结果不符合预期的情况。正确保证线程安全的做法是给共享变量的操作加锁(比如threading.Lock()),确保递增操作是原子性的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 04:01:08