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

Python多线程使用random.shuffle导致列表结果异常问题

多线程环境下random.shuffle打乱列表出现值缺失/重复的问题

这个问题我之前也踩过坑!核心原因很明确:random模块的shuffle方法不是线程安全的,numpy的shuffle同理。你现在让多个线程同时对同一个列表对象执行shuffle操作,就会触发线程竞争——比如线程A正在交换列表元素的中途,线程B突然切入修改同一个位置,结果就是元素被覆盖、重复甚至丢失。

为什么会偶发?

这完全取决于系统的线程调度时机:如果某个线程能完整跑完shuffle再切换到下一个线程,结果就正常;但如果调度器在shuffle的执行过程中强行切换线程,两个线程的修改操作互相干扰,就会出现异常结果。

解决方案

最推荐的是让每个线程操作列表的独立副本,这样彻底避免多线程竞争,效率也更高:

#!/usr/bin/python3 -tt
import random
from threading import Thread

class Th(Thread):
    def __init__ (self, num, c):
        Thread.__init__(self)
        self.c = c
        self.num = num
    def run(self):
        # 复制原列表得到独立副本,每个线程打乱自己的副本
        shuffled_c = self.c.copy()
        random.shuffle(shuffled_c)
        for i in shuffled_c:
            print(f"{self.num} - {i}")

def main():
    # with语句会自动关闭文件,无需手动调用close
    with open('file.txt', 'r') as cmddb:
        c = [cmd.strip() for cmd in cmddb]
    print('ref:')
    for i in c:
        print(i)
    print('----')
    for thread_number in range(5):
        thread = Th(thread_number, c)
        thread.start()

if __name__ == '__main__':
    main()

如果因为特殊需求必须共享原列表(非常不推荐),那就要用锁来同步shuffle操作,确保同一时间只有一个线程能修改列表:

#!/usr/bin/python3 -tt
import random
from threading import Thread, Lock

# 创建全局锁,控制shuffle操作的互斥执行
shuffle_lock = Lock()

class Th(Thread):
    def __init__ (self, num, c):
        Thread.__init__(self)
        self.c = c
        self.num = num
    def run(self):
        global shuffle_lock
        # 加锁后执行shuffle,避免并发修改冲突
        with shuffle_lock:
            random.shuffle(self.c)
            # 注意:这里打印的是刚打乱后的原列表,后续线程会再次打乱它
            for i in self.c:
                print(f"{self.num} - {i}")

def main():
    with open('file.txt', 'r') as cmddb:
        c = [cmd.strip() for cmd in cmddb]
    print('ref:')
    for i in c:
        print(i)
    print('----')
    for thread_number in range(5):
        thread = Th(thread_number, c)
        thread.start()

if __name__ == '__main__':
    main()

关于numpy的情况

numpy的np.random.shuffle同样不是线程安全的,解决思路完全一致:要么给shuffle加锁,要么每个线程复制数组副本,并用独立的随机生成器打乱(避免全局随机状态被多线程干扰):

import numpy as np
from threading import Thread

class Th(Thread):
    def __init__ (self, num, arr):
        Thread.__init__(self)
        self.arr = arr
        self.num = num
    def run(self):
        # 复制数组得到独立副本
        shuffled_arr = self.arr.copy()
        # 每个线程用自己的随机生成器,避免全局状态冲突
        rng = np.random.RandomState()
        rng.shuffle(shuffled_arr)
        for i in shuffled_arr:
            print(f"{self.num} - {i}")

def main():
    arr = np.array([10, 20])
    print('ref:')
    print(arr)
    print('----')
    for num in range(5):
        thread = Th(num, arr)
        thread.start()

if __name__ == '__main__':
    main()

总的来说,尽量不要让多线程共享并修改同一个可变对象,操作副本是最省心、高效的方式~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:52:42