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

Python线程与锁操作全局变量行为不符,问题出在哪里?

线程并发时print输出重复值的问题排查

我编写了如下Python代码:

from threading import Thread, Lock
from time import sleep  # 原代码漏了该导入,先补上

i = 1
lock = Lock()
def t_func():
    global i
    while True:
        lock.acquire()
        local_i = i
        i += 1
        lock.release()
        sleep(1)
        print(i)

预期每个线程始终输出唯一的i值,但运行30个并发线程时出现如下重复输出:

743743
744
745

747
748
749
750
751
752
753
754754
755

757
758

请问我哪里出错了?


问题根源

你的锁只保护了i的递增操作,但完全没管print输出的过程。

多个线程完成i +=1后,会一起进入sleep(1),随后几乎同时触发print(i)。而Python的print函数本身不是线程安全的——它输出字符串到控制台的过程可能被其他线程打断,导致多个线程的输出内容直接叠加,看起来就像重复的数值。比如线程A刚输出"743"还没换行,线程B就输出了另一个"743",最终就出现了"743743"的错乱结果。

另外,原代码漏导入了sleep函数,但这不是输出重复的直接原因。

修复方案

把print操作也放到锁的保护范围内,确保每个线程的输出过程是原子性的:

方案1(推荐,逻辑更合理)

直接在锁内输出线程拿到的原始值,避免后续i被其他线程修改导致的输出偏差:

from threading import Thread, Lock
from time import sleep

i = 1
lock = Lock()
def t_func():
    global i
    while True:
        lock.acquire()
        local_i = i
        i += 1
        print(local_i)  # 输出线程自己拿到的唯一值
        lock.release()
        sleep(1)

方案2(保留sleep后输出的逻辑)

如果一定要在sleep后输出,那输出时也要加锁:

from threading import Thread, Lock
from time import sleep

i = 1
lock = Lock()
def t_func():
    global i
    while True:
        # 先加锁拿到当前值并递增
        lock.acquire()
        current_i = i
        i += 1
        lock.release()
        
        sleep(1)
        
        # 输出时再次加锁,确保输出不被打断
        lock.acquire()
        print(current_i)
        lock.release()

补充说明

原代码里print(i)输出的是递增后的i值,而不是线程自己拿到的local_i——比如线程A拿到local_i=743,i变成744;线程B接着拿到local_i=744,i变成745。两个线程sleep后都会输出745,这本身就会导致重复值。所以输出local_i才是符合"每个线程输出唯一值"预期的做法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 21:20:30