在阅读《java nio》这本书的时候,这本书中提到,FileLock 是进程级的。
在线程级上:如果一个线程在某个文件上获得了一个独占锁,然后第二个线程利用一个单独打开的通道来请求该文件的独占锁,那么第二个线程的请求会被批准。
试了一下,总结了在进程级上运行的几点:
<1>当使用独占锁的时候,除了该进程其他的进程都不能访问被锁定的文件,其他进程会阻塞在 lock() 代码处;
<2>当使用独占锁的时候,该进程可以对文件进行写操作,因为这是其他试图获取锁的会被阻塞;此时执行写操作是线程安全的;
<3>当使用共享锁的时候,所有其他进程都可以获取锁,并且可以并行的进行读操作;
<4>当使用共享锁的时候,调用 write 方法修改会抛出异常,因为所有的进程都可以获取读文件锁,执行写操作是线程不安全的。
public class FileLockTest {
public static void main(String[] args) throws IOException {
RandomAccessFile raf1 = new RandomAccessFile("test.dat", "rw");
//RandomAccessFile raf2 = new RandomAccessFile("test.dat", "rw");
FileChannel channel1 = raf1.getChannel();
//FileChannel channel2 = raf2.getChannel();
new Task(channel1).start();
//new Task(channel2).start();
}
}
class Task extends Thread{
FileChannel channel;
public Task(FileChannel channel){
this.channel = channel;
}
@Override
public void run(){
FileLock fileLock = null;
try{
System.out.println("Try lock file!");
//fileLock = channel.lock(0, channel.size(), false);
fileLock = channel.lock(0, channel.size(), true);
ByteBuffer buffer = ByteBuffer.allocate(10);
channel.read(buffer);
System.out.println(Arrays.toString(buffer.array()));
System.out.println("Locked!");
while(true){
//保持持有文件锁
}
} catch (IOException e) {
e.printStackTrace();
} catch(Exception ex){
ex.printStackTrace();
}finally{
if(fileLock!=null){
try {
fileLock.release();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
通过修改代码可并多次执行改程序以验证这几点,但是关于进程级的文件锁却有一点问题,因为不管如何,我在取消掉main() 方法的注释之后执行多个线程获取锁的操作都会抛出
java.nio.channels.OverlappingFileLockException
这是为什么呢?