ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2021-12-19 12:03:02  阅读:186  来源: 互联网

标签:文件 加锁 end -- start LENGTH JAVA out


在代码中,可以通过 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

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

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

标签:文件,加锁,end,--,start,LENGTH,JAVA,out
来源: https://blog.csdn.net/BaymaxCS/article/details/122021368

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有