ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
<!-- Locking Portions of a Mapped File --> ### 映射文件的部分锁定 文件映射通常用于非常大的文件。你可能需要锁定此类文件的某些部分,以便其他进程可以修改未锁定的部分。例如,数据库必须同时对许多用户可用。这里你可以看到两个线程,每个线程都锁定文件的不同部分: ```java // newio/LockingMappedFiles.java // (c)2017 MindView LLC: see Copyright.txt // 我们无法保证该代码是否适用于其他用途。 // 访问 http://OnJava8.com 了解更多本书信息。 // Locking portions of a mapped file import java.nio.*; import java.nio.channels.*; import java.io.*; public class LockingMappedFiles { static final int LENGTH = 0x8FFFFFF; // 128 MB static FileChannel fc; public static void main(String[] args) throws Exception { fc = new RandomAccessFile("test.dat", "rw") .getChannel(); MappedByteBuffer out = fc.map( FileChannel.MapMode.READ_WRITE, 0, LENGTH); for(int i = 0; i < LENGTH; i++) out.put((byte)'x'); new LockAndModify(out, 0, 0 + LENGTH/3); new LockAndModify( out, LENGTH/2, LENGTH/2 + LENGTH/4); } private static class LockAndModify extends Thread { private ByteBuffer buff; private int start, end; LockAndModify(ByteBuffer mbb, int start, int end) { this.start = start; this.end = end; mbb.limit(end); mbb.position(start); buff = mbb.slice(); start(); } @Override public void run() { try { // Exclusive lock with no overlap: FileLock fl = fc.lock(start, end, false); System.out.println( "Locked: "+ start +" to "+ end); // Perform modification: while(buff.position() < buff.limit() - 1) buff.put((byte)(buff.get() + 1)); fl.release(); System.out.println( "Released: " + start + " to " + end); } catch(IOException e) { throw new RuntimeException(e); } } } } ``` 输出结果: ``` Locked: 75497471 to 113246206 Locked: 0 to 50331647 Released: 75497471 to 113246206 Released: 0 to 50331647 ``` **LockAndModify** 线程类设置缓冲区并创建要修改的 `slice()`,在 `run()` 中,锁在文件通道上获取(不能在缓冲区上获取锁—只能在通道上获取锁)。`lock()` 的调用非常类似于获取对象上的线程锁 —— 现在有了一个“临界区”,可以对文件的这部分进行独占访问。[^1] 当 JVM 退出或关闭获取锁的通道时,锁会自动释放,但是你也可以显式地调用 **FileLock** 对象上的 `release()`,如上所示。 <!-- 脚注 --> [^1]:更多详情可参考[附录:并发底层原理](./book/Appendix-Low-Level-Concurrency.md)。