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

Python线程锁使用疑问:为何A无法始终紧跟B输出?

多线程锁问题分析与解决

问题1:为何子线程1的A、B会被其他字符打断?

原因分析

你仅给子线程1的A、B代码块加了锁,但子线程2对全局变量str的修改完全未使用同一把锁做保护。

Python中str += 'X'并非原子操作,实际分为三步:读取当前str值、拼接新字符、将结果赋值回str。当子线程1持有锁执行A、B的修改时,子线程2因无需获取锁,可在任意时机(包括子线程1执行锁内代码的过程中)抢占CPU修改str,导致A、B之间被插入其他字符。

此外代码还有两个潜在问题:

  • 全局变量命名str与Python内置类型冲突,易引发混淆
  • 判断len(str) >= MAX_LEN和截断str = str[:MAX_LEN]的操作未加锁,多线程场景下会出现竞态条件

解决方法

所有对全局变量str的修改操作(包括读取后修改、截断)必须使用同一把锁保护,确保同一时间只有一个线程能修改str。


问题2:修改锁后输出不够随机的原因及解决方法

原因分析

修改后的代码给单个字符修改操作都加了锁,但每个锁块仅执行一次字符修改,释放锁后线程可能因Python GIL调度机制,连续获得CPU执行权,导致出现连续的ABC或DEF序列,无法得到交错的随机输出。

解决方法

若希望线程更随机地交错执行,可在每个锁块执行完成后,主动让线程让出CPU,给其他线程执行机会。最简单的方式是添加短暂休眠触发线程调度:

示例修正代码:

import threading
import time

# 重命名全局变量,避免与内置类型冲突
result_str = ""
MAX_LEN = 70
lock = threading.Lock()

def function_sub1(): 
    global result_str
    while True:
        with lock:
            result_str += 'A'
            print(f"sub 1 - block 1: {result_str}")
            result_str += 'B'
            print(f"sub 1 - block 2: {result_str}")
        
        # 主动让出CPU,触发线程调度
        time.sleep(0.001)
        
        with lock:
            result_str += 'C'
            print(f"sub 1 - block 3: {result_str}")
        
        time.sleep(0.001)
        
        with lock:
            if len(result_str) >= MAX_LEN:
                result_str = result_str[:MAX_LEN]
                break

def function_sub2(): 
    global result_str
    while True:
        with lock:
            result_str += 'D'
            print(f"sub 2 - block 1: {result_str}")
        
        time.sleep(0.001)
        
        with lock:
            result_str += 'E'
            print(f"sub 2 - block 2: {result_str}")
        
        time.sleep(0.001)
        
        with lock:
            result_str += 'F'
            print(f"sub 2 - block 3: {result_str}")
            
            if len(result_str) >= MAX_LEN:
                result_str = result_str[:MAX_LEN]
                break

sub_thread1 = threading.Thread(target=function_sub1) 
sub_thread2 = threading.Thread(target=function_sub2) 

sub_thread1.start() 
sub_thread2.start()

sub_thread1.join() 
sub_thread2.join()

print("fin:", result_str, "with len:", len(result_str))

若需保持A、B始终绑定(即AB作为不可拆分的整体),同时让C与其他线程操作交错,只需维持A、B在同一个锁块内,配合锁保护所有修改操作+主动休眠,即可得到类似ABDEABCABF...的随机交错结果。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 15:15:00