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

Java多线程读写JSON文件如何互斥?解决文件异常与损坏问题

多线程安全读写JSON文件的解决方案

1. 修复Semaphore的正确使用逻辑

你之前用Semaphore没解决问题,大概率是没把读-修改-写的完整流程包裹在信号量的临界区内,或者异常时没释放许可。正确的写法应该是:

@Override
public void run() {
    File jsonFile = new File("你的JSON文件路径");
    try {
        smp.acquire(); // 获取独占许可,进入临界区
        // 读取JSON内容
        String content = Files.readString(jsonFile.toPath());
        JSONObject json = new JSONObject(content);
        // 执行你的更新操作
        json.put("targetKey", "updatedValue");
        // 写回文件
        Files.writeString(jsonFile.toPath(), json.toString());
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        smp.release(); // 无论是否异常,必须释放许可
    }
}

核心是把文件操作的完整逻辑放在acquire和release之间,不能拆分锁读或锁写。

2. 用ReentrantLock替代Semaphore(更直观的独占锁)

ReentrantLock语义更清晰,专门用于独占式锁场景,同样要在finally块释放锁:

// 全局锁实例,所有MyTask共享同一个
Lock fileLock = new ReentrantLock();

// MyTask的run方法内
@Override
public void run() {
    File jsonFile = new File("你的JSON文件路径");
    fileLock.lock();
    try {
        // 读JSON、修改、写回的完整逻辑
        String content = Files.readString(jsonFile.toPath());
        JSONObject json = new JSONObject(content);
        json.put("targetKey", "updatedValue");
        Files.writeString(jsonFile.toPath(), json.toString());
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        fileLock.unlock();
    }
}

3. 文件系统级别的FileLock(跨进程安全)

如果需要跨JVM进程的线程安全,或者担心JVM层面锁失效,可以用NIO的FileLock:

@Override
public void run() {
    File jsonFile = new File("你的JSON文件路径");
    try (RandomAccessFile raf = new RandomAccessFile(jsonFile, "rw");
         FileChannel channel = raf.getChannel()) {
        // 获取独占锁,通道关闭时自动释放
        FileLock lock = channel.lock();
        // 读取文件内容
        raf.seek(0);
        byte[] buf = new byte[(int) channel.size()];
        raf.read(buf);
        JSONObject json = new JSONObject(new String(buf));
        // 修改内容
        json.put("targetKey", "updatedValue");
        // 清空原文件并写入新内容
        raf.setLength(0);
        raf.seek(0);
        raf.write(json.toString().getBytes());
        lock.release();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

4. 内存缓存+单线程写回(高并发场景优化)

如果并发量高,频繁锁文件会影响性能,可以把JSON内容缓存到内存,用线程安全容器存储,再由单线程统一处理持久化:

// 全局线程安全缓存,初始化时加载文件内容
private static final ConcurrentHashMap<String, JSONObject> jsonCache = new ConcurrentHashMap<>();
static {
    try {
        String content = Files.readString(Paths.get("你的JSON文件路径"));
        jsonCache.put("config", new JSONObject(content));
    } catch (IOException e) {
        e.printStackTrace();
    }
}

// MyTask只操作内存缓存
@Override
public void run() {
    // 原子性修改缓存内容
    jsonCache.compute("config", (key, oldJson) -> {
        oldJson.put("targetKey", "updatedValue");
        return oldJson;
    });
    // 用单线程池触发写回操作,避免多线程写文件
    Executors.newSingleThreadExecutor().submit(() -> {
        try {
            Files.writeString(Paths.get("你的JSON文件路径"), jsonCache.get("config").toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 12:25:28