JAVA realizes file locking and tamper proof -- JAVA programming thought 83

In the code, you can lock the code fragment through the synchronized keyword. Suppose we need to lock the file, and synchronized can only lock the JAVA execution code. What if another thread operating the file is another local thread in the operating system? At this time, it is obviously not possible to lock only through the synchronized keyword.

But fortunately, JDK 1.4 introduces a file locking mechanism for the local operating system. Let's learn with you.

    public static void main(String[] args) throws IOException, InterruptedException {
        //Get the file. The second parameter is whether to append write. It is not set to overwrite the whole file by default
        FileOutputStream fos = new FileOutputStream("D:\\test\\bigFile.txt", true);
        //Get file channel
        FileChannel fc = fos.getChannel();
        //Attempt to lock the file
        FileLock fl = fc.tryLock();
        // If FileLock is not equal to null, locking succeeds
        if (fl != null) {
            System.out.println("Locked File");
            //Specifies that the thread sleeps for 10 seconds
            TimeUnit.SECONDS.sleep(10);
            //Release lock
            fl.release();
            System.out.println("Released Lock");
        }
        //Close flow
        fos.close();
    }
Locked File
Released Lock

getChannel() gets the channel FileChannel, which can call tryLock() and lock() to lock the file.

tryLock() is non blocking. It tries to obtain the lock. If it cannot be obtained (when other threads have obtained the lock and do not share the lock), it will return directly.

lock() is blocking. It will block until the lock can be obtained, or the thread calling lock() is interrupted and the channel calling lock() is closed.

release() releases the lock.

We can also lock part of the file:

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

The first parameter is the start position, the second parameter is the end position, and the third parameter is whether it is a shared lock.

It is worth mentioning that the parameter free locking method will lock the whole file, and the locking area will change with the size of the file; Fixed size locks do not change with the file size, that is, areas beyond size - position will not be locked.

The operating system must support shared locks before it can be used. It can be queried through isShared().

Finally, an example of locking by mapping parts of a file is demonstrated. Different threads lock different parts of the file. They can be modified at the same time. For example, our database is based on this principle.

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);
            //Intercept the area between position and limit as a new buffer
            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) {
                    //Change the ASCII code + 1 of x to 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

This sharing is over. I hope this article will help you. If you can light the like button below, I'd be grateful. Thank you for your [spiritual support].

If you have any questions, you are also welcome to communicate with me. If there are deficiencies, you are also welcome to correct!

Keywords: Java Back-end NIO io

Added by Otoom on Sun, 19 Dec 2021 09:52:53 +0200