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

Python 3.5多线程报错:进程退出码-1073741819(0xC0000005)

解决Python多线程下Exit Code -1073741819 (0xC0000005)的问题

先给你明确这个错误的本质:0xC0000005是Windows系统下的访问违规(Access Violation),简单说就是程序试图访问了不允许它操作的内存区域,结合你的多线程场景,大概率和共享资源的线程冲突、不安全的内存操作有关。下面是针对性的排查和解决方向:

1. 主线程未等待子线程完成就执行文件保存

你当前的代码启动线程后立刻调用np.savetxt,这时候子线程可能还在运行甚至还没开始修改数组,不仅会导致保存的文件不完整,更关键的是:线程后台修改数组的同时主线程在读写数组,很容易触发内存访问冲突。

修复方法:把线程对象存起来,用join()等待所有子线程执行完毕再保存文件:

if __name__ == "__main__":
    # ... 你的数据读取、数组初始化代码 ...
    
    # 存储线程对象
    threads = []
    threads.append(threading.Thread(target=calculation, args=(0,)))
    threads.append(threading.Thread(target=calculation, args=(6,)))
    threads.append(threading.Thread(target=calculation, args=(12,)))
    threads.append(threading.Thread(target=calculation, args=(18,)))
    
    # 启动所有线程
    for t in threads:
        t.start()
    
    # 等待所有线程执行完成
    for t in threads:
        t.join()
    
    # 现在再执行保存操作
    np.savetxt('threshold_'+str(1)+'.csv', data_table_t1, delimiter=',', fmt='%10.5f')
    # ... 其他savetxt代码 ...

2. 多线程共享numpy数组的线程安全问题

numpy数组的内存是连续的,且绝大多数numpy操作都不是原子操作——多个线程同时读写同一个data_table_t1这类数组时,会出现多个线程同时修改同一块内存的情况,直接触发内存访问错误。

方案A:每个线程操作独立局部数组,最后合并(推荐)

让calculation函数返回自己计算的局部数组,主线程等待所有线程结束后合并结果,完全避免共享内存冲突:

def calculation(arg):
    # 初始化线程专属的局部数组
    local_t1 = np.zeros((101, 10))
    local_t5 = np.zeros((101, 10))
    local_t10 = np.zeros((101, 10))
    local_t20 = np.zeros((101, 10))
    local_t40 = np.zeros((101, 10))
    local_t80 = np.zeros((101, 10))
    
    # ... 你的多层嵌套循环计算逻辑,修改局部数组 ...
    
    return local_t1, local_t5, local_t10, local_t20, local_t40, local_t80

if __name__ == "__main__":
    # ... 其他初始化代码 ...
    
    # 用ThreadPoolExecutor更方便处理带返回值的线程
    from concurrent.futures import ThreadPoolExecutor
    with ThreadPoolExecutor(max_workers=4) as executor:
        results = executor.map(calculation, [0,6,12,18])
    
    # 合并所有线程的结果到全局数组
    for res in results:
        t1, t5, t10, t20, t40, t80 = res
        data_table_t1 += t1
        data_table_t5 += t5
        data_table_t10 += t10
        data_table_t20 += t20
        data_table_t40 += t40
        data_table_t80 += t80
    
    # 保存文件
    # ... savetxt代码 ...

方案B:用线程锁保护数组读写

如果必须共享全局数组,用threading.Lock确保同一时间只有一个线程能操作数组:

# 全局定义线程锁
lock = threading.Lock()

def calculation(arg):
    # ... 你的前置计算逻辑,先处理好要写入的数据 ...
    
    # 修改全局数组前加锁
    with lock:
        # 这里写修改data_table_t1等数组的代码
        data_table_t1[target_index] = calculated_value
        data_table_t5[target_index] = calculated_value
        # ... 其他数组修改操作 ...

注意:加锁会降低多线程效率,因为同一时间只有一个线程能执行锁内代码,所以优先推荐方案A。

3. 检查netCDF数据集的多线程安全性

你全局使用了netcdf_entire_dataset这个Dataset对象,如果calculation函数直接读取该对象的变量,部分旧版本的netCDF4库在多线程环境下读取数据不是线程安全的,也会触发访问违规。

修复方法:

  • 升级netCDF4库:pip install --upgrade netCDF4
  • 让每个线程单独打开/关闭Dataset,避免共享对象:
    def calculation(arg):
        # 每个线程独立打开数据集
        with Dataset("F:/dataset/entire_dataset.nc", "r") as nc:
            rain_models = nc.variables['rain_models']
            # ... 你的计算逻辑 ...
    

4. 排查数组越界问题

你的calculation函数有多层嵌套循环,很可能在循环中访问数组时出现索引超出范围的情况(比如rain_models[i][j]的i/j超过数组维度),这也是触发0xC0000005的常见原因。

你可以先单线程运行(只启动一个线程)测试:如果单线程没问题,那就是多线程共享资源的问题;如果单线程也出错,重点排查循环里的索引是否正确,比如打印循环的索引值,核对是否匹配数组的shape。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:14:40