文件锁与内存映射文件
NIO 提供高级文件操作能力:文件锁防止并发冲突,内存映射文件高效访问大文件。
文件锁(FileLock)
作用
- 防止多个进程同时修改同一文件
- 共享锁允许并发读,独占锁阻止其他读写
获取文件锁
Java
try (FileChannel channel = new FileOutputStream("file.txt").getChannel()) {
// 独占锁(阻止其他读写)
FileLock lock = channel.lock(); // 锁整个文件
// 独占锁(指定范围)
FileLock lock = channel.lock(0, 1024, false);
// 共享锁(允许其他读)
FileLock lock = channel.lock(0, 1024, true);
// 尝试获取锁(非阻塞)
FileLock lock = channel.tryLock();
if (lock != null) {
// 获取成功,执行操作
lock.release(); // 释放锁
}
}
锁类型
| 类型 | 参数 | 说明 |
|---|---|---|
| 独占锁 | shared=false | 阻止其他进程读写 |
| 共享锁 | shared=true | 允许其他进程读 |
注意:FileLock 是进程级别的锁,同一进程内多线程不受限制。锁在 FileChannel.close() 或 lock.release() 时释放。
锁的范围
Java
// 锁整个文件
FileLock lock = channel.lock();
// 锁部分区域
FileLock lock = channel.lock(0, 1024, false); // 锁前 1024 字节
内存映射文件(MappedByteBuffer)
作用
- 将文件直接映射到内存
- 通过内存操作文件,减少 IO 调用
- 适合大文件随机读写
创建内存映射
Java
try (FileChannel channel = new FileInputStream("large.bin").getChannel()) {
// 映射文件到内存
MappedByteBuffer buffer = channel.map(
FileChannel.MapMode.READ_ONLY, // 只读模式
0, // 起始位置
channel.size() // 映射大小
);
// 直接操作内存
byte b = buffer.get(0); // 读取
}
try (FileChannel channel = new RandomAccessFile("large.bin", "rw").getChannel()) {
// 读写模式映射
MappedByteBuffer buffer = channel.map(
FileChannel.MapMode.READ_WRITE,
0,
channel.size()
);
buffer.put(0, (byte) 100); // 写入
buffer.force(); // 强制写入磁盘
}
MapMode 模式
| 模式 | 说明 |
|---|---|
| READ_ONLY | 只读,修改抛异常 |
| READ_WRITE | 读写,修改写入文件 |
| PRIVATE | 读写,修改不写入文件(写时复制) |
大文件分段映射
Java
long fileSize = channel.size();
long chunkSize = 1024 * 1024 * 100; // 100MB 一段
for (long pos = 0; pos < fileSize; pos += chunkSize) {
long size = Math.min(chunkSize, fileSize - pos);
MappedByteBuffer buffer = channel.map(MapMode.READ_ONLY, pos, size);
// 处理当前段
}
限制:MappedByteBuffer 最大映射大小受 Integer.MAX_VALUE 限制(约 2GB),大文件需分段映射。
性能对比
| 方式 | 特点 |
|---|---|
| 传统 IO | 每次读写调用系统 IO,开销大 |
| 内存映射 | 操作内存,系统自动同步,高效 |
内存映射适合:
- 大文件随机读写
- 高频文件访问
- 文件内容索引搜索
要点总结
- FileLock 防止多进程并发冲突,进程级锁
- 独占锁阻止其他读写,共享锁允许并发读
- lock() 阻塞获取,tryLock() 非阻塞尝试
- MappedByteBuffer 将文件映射到内存
- READ_ONLY/READ_WRITE/PRIVATE 三种映射模式
- 内存映射适合大文件,超过 2GB 需分段映射
- force() 强制将修改写入磁盘
📝 发现内容有误?点击此处直接编辑