Java NIO:文件锁——FileLock

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)

说明共享锁别人也不能写

猜你喜欢

转载自blog.csdn.net/qq_25805331/article/details/108686767