文件所FileLock

1. 概念

  • 共享锁: 共享读操作,但只能一个写(读可以同时,但写不能)。共享锁防止其他正在运行的程序获得重复的独占锁,但是允许他们获得重复的共享锁。
  • 独占锁: 只有一个读或一个写(读和写都不能同时)。独占锁防止其他程序获得任何类型的锁。

2. FileLock FileChannel.lock(long position, long size, boolean shared)

  • shared的含义:是否使用共享锁,一些不支持共享锁的操作系统,将自动将共享锁改成排它锁。可以通过调用isShared()方法来检测获得的是什么类型的锁。

3. lock()和tryLock()的区别:

  • lock()阻塞的方法,锁定范围可以随着文件的增大而增加。无参lock()默认为独占锁;有参lock(0L, Long.MAX_VALUE, true)为共享锁。
  • tryLock()非阻塞,当未获得锁时,返回null.

4. FileLock的生命周期:在调用FileLock.release(),或者Channel.close(),或者JVM关闭

5. FileLock是线程安全的

6. 注意事项:

  • 同一进程内,在文件锁没有被释放之前,不可以再次获取。即在release()方法调用前,只能lock()或者tryLock()一次。
  • 文件锁的效果是与操作系统相关的。一些系统中文件锁是强制性的,就当Java的某进程获得文件锁后,操作系统将保证其它进程无法对文件做操作了。而另一些操作系统的文件锁是询问式的(advisory),意思是说要想拥有进程互斥的效果,其它的进程也必须也按照API所规定的那样来申请或者检测文件锁,不然将起不到进程互斥的功能。所以文档里建议将所有系统都当做是询问式系统来处理,这样程序更加安全也更容易移植。
  • 如何避免死锁:在读写关键数据时加锁,操作完成后解锁;一次性申请所有需要的资源,并且在申请不成功的情况下放弃已申请到的资源

7.异常

    FileOutputStream.getChannel().tryLock(0L, Long.MAX_VALUE, true)获得共享锁, NonReadableChannelException异常,因为共享锁可读不可写,获取共享锁,必须要包含read channel 
    FileInputStream.getChannel().tryLock(0L, Long.MAX_VALUE, true)获得共享锁 可读不可写
    RandomAccessFile(“r”).getChannel().tryLock(0L, Long.MAX_VALUE, true)获得共享锁 可读不可写(拒绝写访问)
    RandomAccessFile(“rw”).getChannel().tryLock(0L, Long.MAX_VALUE, true)获得共享锁 可读不可写(写被锁【文件被占用】),此时虽然有w但是不能写

独占锁 锁持有者可读可写,其他不持有锁者不可读不可写
    FileOutputStream.getChannel().tryLock()获得独占锁 可写不可读(不可读是因为该锁持有者无read channel)
    FileInputStream.getChannel().tryLock()获得独占锁 异常:NonWritableChannelException(独占锁必须可write)
    RandomAccessFile(“rw”).getChannel().tryLock()获得的独占锁 可写可读
    RandomAccessFile(“r”).getChannel().tryLock()获得的独占锁 NonWritableChannelException (独占锁必须可write)

原文地址:https://www.cnblogs.com/QianYue111/p/13704688.html