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!