java nio共享锁需用filechannel.lock/trylock并设shared=true,必须以读写模式打开通道,锁定范围需显式指定,锁由os管理且须显式释放。

Java NIO 中用 FileLock 实现文件级共享锁,核心是调用 FileChannel.lock(long position, long size, boolean shared) 或 tryLock(...) 并将第三个参数设为 true。共享锁允许多个进程同时读取文件,但会阻止任何进程获取重叠的独占锁(即写操作会被阻塞)。
必须用可读写通道打开文件
即使只打算读、不写,也必须以读写模式打开文件通道——因为只读通道(如 FileInputStream.getChannel())无法加锁,会抛 NonWritableChannelException。
- 推荐方式:
RandomAccessFile("file.txt", "rw").getChannel() - 或:
Files.newByteChannel(path, READ, WRITE) - 避免:
new FileInputStream(...).getChannel().tryLock()(直接失败)
显式指定共享锁参数
无参的 lock() 和 tryLock() 默认申请独占锁;要获得共享锁,必须使用带参重载方法,并传入 true:
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
- 锁定整个文件:
channel.lock(0L, Long.MAX_VALUE, true) - 锁定某一段(例如第100–200字节):
channel.tryLock(100L, 100L, true) - 调用后可用
fileLock.isShared()验证是否真拿到共享锁(某些系统不支持共享锁时会自动降级为独占锁)
注意跨进程行为与释放时机
共享锁由操作系统管理,对所有进程可见:多个进程可各自持有一份共享锁,但只要有一个共享锁存在,其他进程就无法对该范围加独占锁。
- 锁不会因 JVM 退出或异常自动释放,必须显式调用
fileLock.release() - 建议在
finally块中释放,或配合try-with-resources关闭通道(关闭通道会间接释放锁,但显式release()更可靠) - 同一 JVM 内重复对同一区域加共享锁会抛
OverlappingFileLockException
典型使用场景示例
比如多个服务进程需并发读配置文件,但禁止任何进程在读期间修改它:
- 每个进程启动时尝试加共享锁:
FileLock lock = channel.tryLock(0L, Long.MAX_VALUE, true) - 若返回
null,说明有进程正以独占方式持有该文件(可能在写),可等待或报错 - 加锁成功后读取内容,读完立即
lock.release() - 写操作方则必须用
tryLock(0L, Long.MAX_VALUE, false),只有所有共享锁都释放后才能成功
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










