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

Java/Kotlin中File实例是否线程安全?多线程/协程并发写文件丢行问题

核心结论

java.io.File 实例只是文件系统路径的轻量包装,不代表对底层物理文件的独占访问权。哪怕每个线程/协程都持有独立的局部File实例,只要这些实例指向磁盘上同一路径的文件,本质上都是在操作同一个文件,并发写入必然会出现内容覆盖、行丢失的问题。

代码中存在的两个具体并发缺陷

  • 文件存在性检查与文件创建、写入操作非原子,存在竞态
    多个协程同时首次触发写入时,可能同时通过!file.exists()判断,全部进入新建文件分支。后执行createNewFile()的协程会直接覆盖之前协程创建并写入了内容的文件,导致已写入的表头、记录直接丢失。
  • 多写入端同时打开文件追加写入无同步保障
    即使所有协程都进入追加写入分支,BufferedWriter自带内存缓冲区,多个写入端的缓冲区刷新顺序不可控,叠加操作系统层面普通文件写入无原子性保障,会出现内容交错、部分缓冲区内容被覆盖的问题,直接表现为部分行丢失、内容错位。

问题复现代码

private val noOfThreads = newFixedThreadPoolContext(nThreads = 3, name = "coRoutineThreads")
val nameOfFile = "test.csv"
fun coRoutineFunction(){
    runBlocking{
        for(i in 1..100)
        {
            async(noOfThreads){
               writeToFile(nameOfFile)
            }
        }
    }
}

fun writeToFile(nameOfFile){
    val file = File(fileName)
    // 基于bufferedWriter和CSVPrinter执行写入
}

存在缺陷的写入实现

internal fun writeToFile(fileName: String, recordList: List<Map<String, String>>) {
try {
    val file = File(fileName)
    if (!file.exists()) {
        file.createNewFile()
        val writer = FileWriter(file)
        val bufferedWriter = BufferedWriter(writer)
        writeCSVRecordWithHeader(bufferedWriter, recordList)
        bufferedWriter.close()
    } else {
        val writer = FileWriter(file, true)
        val bufferedWriter = BufferedWriter(writer)
        concCSVRecord(bufferedWriter, recordList)
        bufferedWriter.close()
    }
} catch (exception: Exception) {
    logger.error("Exception at writeRecordsToFile while creating file: ${ExceptionUtils.getStackTrace(exception)}")
    throw exception
}
}

修复方案
  • 对同个文件的全流程写入操作加互斥同步
    协程场景下可以用Mutex为每个文件路径绑定独立的锁实例,将「检查文件是否存在、创建文件/打开追加流、写入内容、关闭流」的完整逻辑包裹在锁范围内,保证同一时间只有一个协程执行写入操作,从根本上消除竞态。
  • 采用单协程统一写入的架构避免多端并发写
    单独启动一个专属写入协程,所有待写入的CSV记录通过Channel发送到这个协程,由它统一负责文件的打开、初始化、写入全流程。这种方案没有锁的性能开销,也从架构上杜绝了多写入端同时操作同一个文件的可能,是协程场景下的最优实现。
  • 剥离文件初始化逻辑
    把「创建文件、写入CSV表头」的逻辑从每次写入的分支判断中移除,只在程序启动后第一次写入前执行一次,消除存在性检查带来的竞态点。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 21:12:19