File Locking
起初听起来”锁定文件“有点令人迷惑。好像指的是组织程序或者用户去访问特定的文件。但实际上,文件锁定和普通的java对象的锁定一样,他们不会阻止任何访问数据的方式,相反,他还通过共享锁来允许不同部分的系统协调。
你可以锁定部分文件,也可以锁定全部文件。如果你获得了一个排他锁,那么其他的所有人将不能在此文件的相同部分获得锁。如果你获得了一个共享锁,那么其他人还是可以获得共享锁,只是不能获取排它锁了。文件锁也不是仅仅用来保护数据,举例来说:你可能暂时的锁住一个文件来保证特定的写入操作是原子性的,不被其他进程所干扰。
大多数操作系统都提供了文件锁,但做法却不一样。有些提供共享锁,有些仅仅提供排它锁,有的都提供。事实上,锁定部分文件是很难实现的,虽然大多数情况下没必要。
Locking a file
为了获得文件部分锁,你可以在打开一个FileChannel后调用lock( )方法,注意如果你想获得排它锁,就不得不以写入的方式打开一个文件。
RandomAccsessFile raf = new RandomAccessFile( "usefilelocks.txt" ," rw " );
FileChannel fc = raf.getChannel();
FileLock lock = fc.lock( start,end,false );
在你获得锁之后,你可以执行一些你需要做的敏感的操作,然后释放该锁。
lock.release();
在你释放该锁之后,其他程序将有平等的机会去获得该锁。
为了更好的理解file lock,我们来编写一个程序:UseFileLocks.java,他将在运行是获得一个文件的锁,然后保持3秒后释放,如果你在同时运行另外一个实例,则可以看到另一个程序处于阻塞状态。
package com.nio.example;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
/**
* 文件锁定测试
*/
public class UseFileLocks {
public static void main(String[] args) throws Exception {
RandomAccessFile raf = new RandomAccessFile("./src/ex_txt", "rw");
FileChannel fc = raf.getChannel();
System.out.println( "将要获得文件锁" );
//FileLock lock = fc.lock(0,raf.length(),true); //共享锁,不阻塞共享锁的获取
FileLock lock = fc.lock(); //排它锁,阻塞所有锁的获取
System.out.println( "获得文件锁" );
Thread.sleep(5000);
lock.release();
System.out.println( "释放文件锁" );
}
}
文件锁及其可移植性
文件锁有时是不可依赖的,尤其是在不同的操作系统实现不同的锁机制的情况下,下面的建议可以帮助你的程序是稳定的:
- 仅仅使用排它锁
- 将所有的锁看作是一个可能(即不保证能怎么怎么样,只是尽可能的怎么怎么样)。