JAVA实现对文件加锁防篡改 --《JAVA编程思想》83

2021/12/19 12:19:31

本文主要是介绍JAVA实现对文件加锁防篡改 --《JAVA编程思想》83,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

在代码中,可以通过 synchronized 关键字对代码片段进行加锁,假设我们需要对文件进行加锁,synchronized 只能对 JAVA 执行代码进行加锁,倘若另外一个操作文件的线程是操作系统中其他的某个本地线程呢?这时仅仅通过 synchronized 关键字来加锁显然是不行的。

但好在 JDK 1.4 引入了针对本地操作系统的文件加锁机制,下面便和大家一起来学习。

    public static void main(String[] args) throws IOException, InterruptedException {
        //获取文件,第二个参数为是否追加写,不设置为默认覆盖整个文件
        FileOutputStream fos = new FileOutputStream("D:\\test\\bigFile.txt", true);
        //获取文件通道
        FileChannel fc = fos.getChannel();
        //尝试对文件加锁
        FileLock fl = fc.tryLock();
        // FileLock不等于null则加锁成功
        if (fl != null) {
            System.out.println("Locked File");
            //指定线程睡眠10秒
            TimeUnit.SECONDS.sleep(10);
            //释放锁
            fl.release();
            System.out.println("Released Lock");
        }
        //关闭流
        fos.close();
    }
Locked File
Released Lock

getChannel() 获取通道 FileChannel ,它可以调用 tryLock() 和 lock() 对文件进行加锁。

tryLock() 是非阻塞式的,它设法获取锁,如果获取不到(其他线程已拿到锁,并且不共享锁时),则会直接返回。

lock() 是阻塞式的,它会一直阻塞直到可以获得锁,或者调用 lock() 的线程中断、调用 lock() 的通道关闭。

release() 会释放锁。

我们也可以对文件的一部分加锁:

 tryLock(long position, long size, boolean shared)
lock(long position, long size, boolean shared)

第一个参数为起始位置,第二个参数为结束位置,第三个参数为是否为共享锁。

值得一提的是,无参数的加锁方法会对整个文件进行加锁,加锁区域会随着文件的尺寸而进行变化;固定尺寸的锁不随文件尺寸做出变化,即超出 size - position 之外的区域是不会被锁定的。

操作系统必须支持共享锁才可以进行使用,可以通过 isShared() 来查询。

最后,演示一个通过映射文件的部分进行加锁的例子,不同的线程对文件的不同部分进行加锁,两者可以同时修改,像我们的数据库就是基于这种原理。

public class LockingMappedFiles {

    //128MB
    private static final int LENGTH = 0X8FFFFFF;

    private static FileChannel fc;

    private static class LockAndModify extends Thread {

        private ByteBuffer buffer;

        private int start, end;

        public LockAndModify(ByteBuffer mbb, int start, int end) {
            this.start = start;
            this.end = end;
            mbb.limit(end);
            mbb.position(start);
            //截取position至limit之间的区域作为新缓冲区
            buffer = mbb.slice();
            start();
        }

        @Override
        public void run() {
            try {
                FileLock fl = fc.lock(start, end, false);
                System.out.println("Locked:" + start + " to " + end);
                while (buffer.position() < buffer.limit() - 1) {
                    //将x的ASCII码+1变成y
                    buffer.put((byte) (buffer.get() + 1));
                }
                fl.release();
                System.out.println("Released:" + start + " to " + end);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws IOException {
        fc = new RandomAccessFile("D:\\test\\bigFile.txt", "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);
    }

}

```java
Locked:0 to 50331647
Locked:75497471 to 113246206
Released:75497471 to 113246206
Released:0 to 50331647

本次分享至此结束,希望本文对你有所帮助,若能点亮下方的点赞按钮,在下感激不尽,谢谢您的【精神支持】。

若有任何疑问,也欢迎与我交流,若存在不足之处,也欢迎各位指正!



这篇关于JAVA实现对文件加锁防篡改 --《JAVA编程思想》83的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程