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。