15.9.5 文件锁
15.9.5 文件锁
文件锁在操作系统中是很平常的事情,如果多个运行的程序需要并发修改同一个文件时,程序之间需要某种机制来进行通信,使用文件锁可以有效地阻止多个进程并发修改同一个文件,所以现在的大部分操作系统都提供了文件锁的功能。
文件锁控制文件的全部或部分字节的访问,但文件锁在不同的操作系统中差别较大,所以早期的JDK
版本并未提供文件锁的支持。从JDK1.4
的NIO
开始,Java
开始提供文件锁的支持。
FileLock
在NIO
中,Java
提供了FileLock
来支持文件锁定功能。
如何获取FileLock
无参的lock和tryLock方法
在FileChannel
中提供的lock()
和tryLock()
两个方法可以获得文件锁FileLock
对象,从而锁定文件。
FileChannel 获取FileLock 的方法 |
描述 |
---|---|
FileLock lock() |
获取FileChannel对应的排它锁 |
FileLock tryLock() |
获取FileChannel对应的排它锁 |
lock方法和tryLock方法的区别
lock()
和tryLock()
方法存在区别:
- 当
lock()
试图锁定某个文件时,如果无法得到文件锁,程序将一直阻塞; - 而
tryLock()
是尝试锁定文件,它将直接返回而不是阻塞,如果获得了文件锁,该方法则返回该文件锁,否则将返回null
部分锁定
如果FileChannel
只想锁定文件的部分内容,而不是锁定全部内容,则可以使用如下的lock()
或tryLock()
方法。
方法 | 描述 |
---|---|
abstract FileLock lock(long position, long size, boolean shared) |
Acquires a lock on the given region of this channel’s file. |
abstract FileLock tryLock(long position, long size, boolean shared) |
Attempts to acquire a lock on the given region of this channel’s file. |
共享锁
带参数的lock
和tryLock
方法的参数shared
为true
时,表明该锁是一个共享锁,它将**允许多个进程来读取该文件,但阻止其他进程获得对该文件的排他锁**。(共享锁:别人可读不可写)
排他锁
带参数的lock
和tryLock
方法的参数shared
为false
时,表明该锁是一个排他锁,它将锁住对该文件的读写。(排它锁:别人不可读,也不可写)
直接使用lock()
或tryLock()
方法获取的文件锁是排他锁
判断是否是共享锁
程序可以通过调用FileLock
的isShared()
方法来判断它获得的锁是否为共享锁。
FileLock 的isShared 方法 |
描述 |
---|---|
boolean isShared() |
Tells whether this lock is shared. |
释放文件锁
处理完文件后通过FileLock
的release()
方法释放文件锁。
FileLock 的release 方法 |
描述 |
---|---|
abstract void release() |
Releases this lock. |
程序 使用FileLock
下面程序示范了使用FileLock
锁定文件的示例。
1 | import java.io.*; |
上面程序中的代码:
1 | FileLock lock = channel.tryLock(); |
用于对指定文件加锁,接着程序调用Thread.sleep(10000)
暂停了10秒后才释放文件锁,因此在这10秒之内,其他程序无法对a.txt
文件进行修改。
文件锁虽然可以用于控制并发访问,但对于高并发访问的情形,还是推荐使用数据库来保存程序信息,而不是使用文件。
文件锁需要注点的地方
关于文件锁还需要指出如下几点。
- 在某些平台上,文件锁仅仅是建议性的,并不是强制性的。这意味着即使一个程序不能获得文件锁,它也可以对该文件进行读写。
- 在某些平台上,不能同步地锁定一个文件并把它映射到内存中
- 文件锁是由
Java
虚拟机所持有的,如果两个Java
程序使用同一个Java
虚拟机运行,则它们不能对同一个文件进行加锁。 - 在某些平台上关闭
FileChannel
时,会释放Java
虚拟机在该文件上的所有锁,因此应该避免对同一个被锁定的文件打开多个FileChannel
。