使用 NIO 完成对资源加锁

x33g5p2x  于2022-05-22 转载在 其他  
字(1.8k)|赞(0)|评价(0)|浏览(228)

一 点睛

给某一个文件加锁,防止并发访问时引起的数据不安全。

在 JUC 中,可以使用 synchronized、Lock 给共享的资源加锁,或者使用 volatile、CAS 算法等防止并发冲突。在 FileChannel 中也提供了类似 Lock 的加锁方式。
public abstract FileLock lock(long position, long size, boolean shared) throws IOException;

shared 参数说明。

true:共享锁。实际上是指“读共享”,某一线程将资源锁住之后,其他线程既只能读、不能写该资源。

false:独占锁。某一线程将资源锁住之后,其他线程既不能读、也不能写该资源。

二 代码

package nio;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;

public class FileLockTest {
    public static void main(String[] args) throws FileNotFoundException, IOException, InterruptedException {
        RandomAccessFile raf = new RandomAccessFile("g:/abc.txt", "rw");
        FileChannel fileChannel = raf.getChannel();
        /*
            将 abc.txt 中 position=2,size=4 的内容加锁(即只对文件的部分内容加了锁)。
            lock()第三个布尔参数的含义如下:
                true:共享锁。实际上是指“读共享”:某一线程将资源锁住之后,其他线程既只能读、不能写该资源。
                false:独占锁。某一线程将资源锁住之后,其他线程既不能读、也不能写该资源。
         */
        // FileChannel 加共享锁
        FileLock fileLock = fileChannel.lock(2, 4, true);
        new Thread(
                () -> {
                    try {
                        byte[] bs = new byte[8];
                        // 新线程对 abc.txt 进行读操作
                        raf.read(bs,0,8);
                        // 新线程对 abc.txt 进行写操作
                        // raf.write("ccccccccc".getBytes(),0,8);
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }).start();
        // 模拟main线程将abc.txt锁3秒的操作
        System.out.println("main线程将abc.txt锁3秒...");
        Thread.sleep(3000);
        System.out.println("3秒结束,main释放锁");
        fileLock.release();
    }
}

三 测试

1 共享锁的读操作

main线程将abc.txt锁3秒...

3秒结束,main释放锁

2 共享锁的写操作——这里会抛异常

main线程将abc.txt锁3秒...

java.io.IOException: 另一个程序已锁定文件的一部分,进程无法访问。

at java.io.RandomAccessFile.writeBytes(Native Method)

at java.io.RandomAccessFile.write(RandomAccessFile.java:525)

at nio.FileLockTest.lambda$main$0(FileLockTest.java:28)

at java.lang.Thread.run(Thread.java:748)

3秒结束,main释放锁

3 独占锁的读操作——这里会等待,不会抛异常

main线程将abc.txt锁3秒...

3秒结束,main释放锁

4 独占锁的写操作——这里会等待,不会抛异常

main线程将abc.txt锁3秒...

3秒结束,main释放锁

修改前文件内容

helloworld

修改后文件内容

ccccccccld

相关文章