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

Python 3多线程性能异常:并行执行耗时反而更长的问题排查

为什么多线程写文件反而比串行慢?

嘿,这个问题我之前也碰到过,其实核心原因和磁盘IO的特性以及你的代码写法都有关系,我来一步步给你拆解:

一、为啥多线程写文件更慢?

1. 磁盘IO天生是串行瓶颈

不管是机械硬盘还是大部分SSD,同一时间只能高效处理一个写入请求。当你开两个线程并行写的时候,操作系统不得不频繁切换线程来分配磁盘资源,这种上下文切换的开销会直接抵消甚至超过并行带来的收益,反而比串行一次写完更慢。

2. 频繁的系统调用放大了开销

看你的代码,循环里做了1000万次f.write()调用——每次write都是一次系统调用(从用户态切换到内核态),这个本身就有不小的开销。而多线程情况下,线程切换+多次系统调用的叠加,会让这个开销变得更大。

3. 同一文件的写入竞争(如果是写同一个文件的话)

如果两个线程写的是同一个文件,哪怕用的是追加模式'a',操作系统为了保证文件写入的原子性,会在底层加锁。两个线程会互相等待对方释放锁,这就相当于变相的串行,还多了线程切换的成本,自然比真正的串行更慢。

二、怎么优化?

1. 先缓存数据,减少系统调用次数

把小批量的写入先缓存到内存里,一次性写入文件,这能把1000万次系统调用降到1次,效率会提升几个数量级。修改后的代码大概是这样:

import timeit
from threading import Thread

def write_File(fName):
    start = timeit.default_timer()
    print(f'writing to {fName}!')
    # 用列表缓存所有内容(比字符串拼接更高效)
    content_buffer = []
    for i in range(0, 10000000):
        content_buffer.append("aadadadadadadadadadadadada" + str(i))
    # 一次性写入文件
    with open(fName, 'a') as f:
        f.write('\n'.join(content_buffer))  # 按行分隔,也可以直接拼接成大字符串
    end = timeit.default_timer()
    print(f"{fName} 耗时: {end - start:.2f}秒")
    print('Fn exit!')

# 测试串行
start_total = timeit.default_timer()
write_File("test1.txt")
write_File("test2.txt")
print(f"串行总耗时: {timeit.default_timer() - start_total:.2f}秒")

# 测试并行
start_total = timeit.default_timer()
t1 = Thread(target=write_File, args=("test1.txt",))
t2 = Thread(target=write_File, args=("test2.txt",))
t1.start()
t2.start()
t1.join()
t2.join()
print(f"并行总耗时: {timeit.default_timer() - start_total:.2f}秒")

2. 避免多线程写同一个文件

如果必须用多线程,尽量让每个线程写不同的文件——如果是SSD的话,可能能并行处理不同文件的写入,这时并行的耗时会接近串行的单线程耗时;如果是机械硬盘,提升可能有限,但至少不会比串行慢。

3. 写同一个文件时,优先用串行

如果最终要合并成一个文件,不如先让多线程写不同的临时文件,最后再串行合并,这样既利用了多线程的优势,又避免了同一文件的写入竞争。

总结

你的核心问题不是多线程本身,而是频繁的小数据写入和磁盘IO的串行特性导致的。先优化写入方式(缓存批量写入),再根据场景选择串行或多线程,就能解决耗时反而更长的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:37:11