NIO学习笔记(八)FileLock文件锁的使用
1、执行锁定的操作
FileLock lock(long position , long size , boolean shared)方法的作用是获取此通道的文件给定区域上的锁定。在可以锁定该区须之前、已关闭此通道之前或者已中断调用线程之前,将阻塞此方法的调用。
再次方法调用期间,如果另一个线程关闭了此通道,则会抛出AsynchronousCloseException异常。如果等待获取锁定的同时中断了调用线程,则将状态设置为中断并抛出FileLockInterruptionException异常。如果调用了此方法时已设置调用方的中断状态,则立即抛出该异常;不更改该线程的中断状态。
-
由position和size参数所指定的区域无须包含在实际的底层文件中,甚至无需与文件重叠。
-
锁定的区域大小是固定的;如果某个已经锁定的区域最初包含整个文件,并且文件因扩大而超出了区域,则该锁定不覆盖此文件的新部分
-
如果期望文件大小扩大并且要求锁定整个文件,则应该锁定不覆盖此文件的新部分,则应该锁定的position从0开始,size传入大于或者等于预计文件的最大值。零参数的lock方法只是锁定大小为Long.MAX_VALUE
1.1、验证FileLock(long position , long size , boolean shared)方法是同步的
接下来做一个小小的实验,代码1如下:
public class FileLockTest1 {
public static void main(String[] args) throws IOException, InterruptedException {
RandomAccessFile fileA = new RandomAccessFile("F:\\Idea-Code\\NIO-Demo\\src\\com\\xiao\\nio\\lock\\FileLockTest1.java","rw");
FileChannel channelA = fileA.getChannel();
System.out.println("A begin");
//给文件的1-2加锁,false表示为独占锁
channelA.lock(1,2,false);
System.out.println("A end");
Thread.sleep(Integer.MAX_VALUE);
//关闭资源
fileA.close();
channelA.close();
}
}
代码2如下:
public class FileLockTest2 {
public static void main(String[] args) throws IOException, InterruptedException{
RandomAccessFile fileA = new RandomAccessFile("F:\\Idea-Code\\NIO-Demo\\src\\com\\xiao\\nio\\lock\\FileLockTest1.java","rw");
FileChannel channelA = fileA.getChannel();
System.out.println("B begin");
//给文件的1-2加锁,false表示为独占锁
channelA.lock(1,2,false);
System.out.println("B end");
Thread.sleep(Integer.MAX_VALUE);
//关闭资源
fileA.close();
channelA.close();
}
}
然后我们运行1,之后在运行2,发现B只输出了B begin。说明这是一把独占锁,且相互抢占资源导致了阻塞。
1.2、验证共享锁自己不能写
注意,如果操作锁定区域,就会出现异常;如果操作未锁定区域,则不出现异常。
请看下面一段代码:
public class FileLockTest3 {
public static void main(String[] args) throws IOException {
RandomAccessFile fileA = new RandomAccessFile("F:\\Idea-Code\\NIO-Demo\\src\\com\\xiao\\nio\\lock\\FileLockTest1.java","rw");
FileChannel channel = fileA.getChannel();
channel.lock(1,2,true);
channel.write(ByteBuffer.wrap("12335145".getBytes()));
}
}
===================================运行结果=====================================
Exception in thread "main" java.io.IOException: 另一个程序已锁定文件的一部分,进程无法访问。
at sun.nio.ch.FileDispatcherImpl.write0(Native Method)
at sun.nio.ch.FileDispatcherImpl.write(FileDispatcherImpl.java:75)
at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
at sun.nio.ch.IOUtil.write(IOUtil.java:65)
at sun.nio.ch.FileChannelImpl.write(FileChannelImpl.java:211)
at com.xiao.nio.lock.FileLockTest3.main(FileLockTest3.java:14)
1.3、验证共享锁别人不能写
接下来看2段代码
先看代码1:
public class FileLockTest4 {
public static void main(String[] args) throws IOException, InterruptedException {
RandomAccessFile fileA = new RandomAccessFile("F:\\Idea-Code\\NIO-Demo\\src\\com\\xiao\\nio\\lock\\FileLockTest1.java","rw");
FileChannel channel = fileA.getChannel();
channel.lock(1,2,true);
Thread.sleep(Integer.MAX_VALUE);
}
}
再看代码2:
public class FileLockTest5 {
public static void main(String[] args) throws IOException {
RandomAccessFile fileA = new RandomAccessFile("F:\\Idea-Code\\NIO-Demo\\src\\com\\xiao\\nio\\lock\\FileLockTest1.java","rw");
FileChannel channel = fileA.getChannel();
channel.write(ByteBuffer.wrap("12335145".getBytes()));
}
}
我们先运行代码1,在运行代码2.你会发现这样的异常
Exception in thread "main" java.io.IOException: 另一个程序已锁定文件的一部分,进程无法访问。
at sun.nio.ch.FileDispatcherImpl.write0(Native Method)
at sun.nio.ch.FileDispatcherImpl.write(FileDispatcherImpl.java:75)
at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
at sun.nio.ch.IOUtil.write(IOUtil.java:65)
at sun.nio.ch.FileChannelImpl.write(FileChannelImpl.java:211)
at com.xiao.nio.lock.FileLockTest5.main(FileLockTest5.java:13)
说明共享锁别人也不能写