Python并发文件写入_锁与同步说明【指导】

Python并发写文件需用锁防竞态:线程间用threading.Lock,进程间用multiprocessing.Lock;也可用队列中转、原子追加或logging模块替代。

多个线程或进程同时向同一个文件写入数据时,不加控制会导致内容错乱、覆盖甚至损坏。Python 中实现安全的并发文件写入,核心在于“避免竞态条件”——即确保同一时刻最多只有一个写操作在执行。这需要借助锁(Lock)或更高级的同步机制,但具体选哪种、怎么用,得看你是线程内并发还是跨进程并发。

线程间写入:用 threading.Lock 最直接

同一进程内的多个线程共享内存和文件描述符,直接 open/write 会互相干扰。解决办法是在写入前加锁,写完释放:

  • 创建一个全局 threading.Lock() 实例(不能每个线程新建一个)
  • 所有写操作必须包裹在 lock.acquire() / lock.release() 或更推荐的 with lock: 块中
  • 注意:锁只保护你的代码逻辑,不自动保护底层系统调用;但对普通文本写入已足够

示例片段:

lock = threading.Lock()
def write_to_file(content):
  with lock:
    with open("log.txt", "a") as f:
      f.write(content + "\n")

多进程写入:不能用 threading.Lock,改用 multiprocessing.Lock

子进程不共享线程锁对象,threading.Lock 在 multiprocessing 中完全无效。必须使用 multiprocessing.Lock,它基于系统级原语(如 semaphores),可在进程间同步:

  • 在主进程中创建 multiprocessing.Lock(),作为参数传给子进程或通过 Manager 共享
  • 子进程中同样用 with lock: 确保临界区互斥
  • 若需更高性能且写入量大,可考虑让各进程写入独立临时文件,最后由主进程合并

更轻量替代方案:避免锁,用原子写入或队列中转

不是所有场景都必须锁文件。以下方式可绕过同步复杂度:

  • 单生产者多消费者?queue.Queue(线程安全)或 multiprocessing.Queue 收集写入请求,由一个专属线程/进程顺序落盘
  • 追加写(append)+ 小数据? Linux/macOS 下 open(..., "a") 的 write 是原子的(只要单次写入 ≤ 4KB),但仅限追加,且不保证多行原子性
  • 日志类场景? 直接用标准库 logging 模块,它内置了线程安全的 FileHandler,支持多线程写入

常见误区提醒

容易忽略但影响稳定的细节:

  • "w" 模式打开文件会清空内容,多线程/进程下极易丢失数据 —— 追加一律用 "a"
  • 文件对象本身不是线程安全的,即使加了锁,也要确保每次写都重新 open / close,或复用同一个 file 对象(但后者需更谨慎管理生命周期)
  • 异步 IO(asyncio)中不能直接用 threading.Lock,应改用 asyncio.Lock,且需配合 async with