转载自  Java 进程间文件锁FileLock详解

最近需要在两个进程中对同一个文件进行操作,正好Java 提供了文件锁FileLock类,利用这个类可以控制不同程序(JVM)对同一文件的并发访问,实现进程间文件同步操作。

FileLock是java 1.4 版本后出现的一个类,它可以通过对一个可写文件(w)加锁,保证同时只有一个进程可以拿到文件的锁,这个进程从而可以对文件做访问;而其它拿不到锁的进程要么选择被挂起等待,要么选择去做一些其它的事情, 这样的机制保证了众进程可以顺序访问该文件。也可以看出,能够利用文件锁的这种性质,在一些场景下,虽然我们不需要操作某个文件, 但也可以通过 FileLock 来进行并发控制,保证进程的顺序执行,避免数据错误。

“Locks are associated with files, not channels. Use locks to coordinate with external processes, not between threads in the same JVM.”

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. 示例代码:

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.util.Date;  public class FileLockTest {  public static void main(String[] args){  FileChannel channel = null;  FileLock lock = null;  try {  //1. 对于一个只读文件通过任意方式加锁时会报NonWritableChannelException异常  //2. 无参lock()默认为独占锁,不会报NonReadableChannelException异常,因为独占就是为了写  //3. 有参lock()为共享锁,所谓的共享也只能读共享,写是独占的,共享锁控制的代码只能是读操作,当有写冲突时会报NonWritableChannelException异常  channel = new FileOutputStream("logfile.txt",true).getChannel();  RandomAccessFile raf = new RandomAccessFile("logfile.txt","rw");  //在文件末尾追加内容的处理  raf.seek(raf.length());  channel = raf.getChannel();  //获得锁方法一:lock(),阻塞的方法,当文件锁不可用时,当前进程会被挂起  lock = channel.lock();//无参lock()为独占锁  //lock = channel.lock(0L, Long.MAX_VALUE, true);//有参lock()为共享锁,有写操作会报异常  //获得锁方法二:trylock(),非阻塞的方法,当文件锁不可用时,tryLock()会得到null值  //do {  //  lock = channel.tryLock();  //} while (null == lock);  //互斥操作  ByteBuffer sendBuffer=ByteBuffer.wrap((new Date()+" 写入\n").getBytes());  channel.write(sendBuffer);  Thread.sleep(5000);  } catch (FileNotFoundException e) {  e.printStackTrace();  } catch (IOException e) {  e.printStackTrace();  } catch (InterruptedException e) {  e.printStackTrace();  } finally {  if (lock != null) {  try {  lock.release();  lock = null;  } catch (IOException e) {  e.printStackTrace();  }  }  if (channel != null) {  try {  channel.close();  channel = null;  } catch (IOException e) {  e.printStackTrace();  }  }  }  }
}  

Java 进程间文件锁FileLock详解相关推荐

  1. Java并发编程最佳实例详解系列

    Java并发编程最佳实例详解系列: Java并发编程(一)线程定义.状态和属性 Java并发编程(一)线程定义.状态和属性 线程是指程序在执行过程中,能够执行程序代码的一个执行单元.在java语言中, ...

  2. 【Java基础】HashMap原理详解

    [Java基础]HashMap原理详解 HashMap的实现 1. 数组 2.线性链表 3.红黑树 3.1概述 3.2性质 4.HashMap扩容死锁 5. BATJ一线大厂技术栈 HashMap的实 ...

  3. 《Java和Android开发实战详解》——1.2节Java基础知识

    本节书摘来自异步社区<Java和Android开发实战详解>一书中的第1章,第1.2节Java基础知识,作者 陈会安,更多章节内容可以访问云栖社区"异步社区"公众号查看 ...

  4. Java中的Runtime类详解

    Java中的Runtime类详解 1.类注释 /**Every Java application has a single instance of class Runtime that allows ...

  5. Java多线程之volatile详解

    Java多线程之volatile详解 目录: 什么是volatile? JMM内存模型之可见性 volatile三大特性之一:保证可见性 volatile三大特性之二:不保证原子性 volatile三 ...

  6. [java] 虚拟机(JVM)底层结构详解[转]

    [java] 虚拟机(JVM)底层结构详解[转] 本文来自:曹胜欢博客专栏.转载请注明出处:http://blog.csdn.net/csh624366188 在以前的博客里面,我们介绍了在java领 ...

  7. Linux进程管理工具 Supervisor详解

    介绍 Supervisor安装与配置(linux/unix进程管理工具) Supervisor(http://supervisord.org)是用Python开发的一个client/server服务, ...

  8. Java使用Jco连接sap详解

    SAP的R/3系统与Java平台一样有着许多类似的技术理念,以及同样广泛的企业级用户,但是它们完全是两个不同的世界.当用户面临流程 或者数据整合方面的需求的时候,就迫切需要一种高效的方式,在R/3系统 ...

  9. Java虚拟机之垃圾回收详解一

    Java虚拟机之垃圾回收详解一 Java技术和JVM(Java虚拟机) 一.Java技术概述: Java是一门编程语言,是一种计算平台,是SUN公司于1995年首次发布.它是Java程序的技术基础,这 ...

最新文章

  1. shell getopt 获取参数
  2. 1040. Longest Symmetric String (25)
  3. 只能在微信浏览器打开的链接,如何查看源码
  4. OMG,隔壁老王竟然是个GEEK !
  5. mysql5.7.24免安装版配置_mysql5.7.20免安装版配置方法图文教程
  6. c语言中执行一次的函数once,iOS只执行一次的方法
  7. Qt Creator快捷键大全
  8. 软件测试——软件开发过程
  9. java实现微信支付
  10. websocket使用指南
  11. 微信 - 微信语音转发好友 / 朋友圈方法
  12. 微信登录(官方指导)
  13. 数据基础---数据可视化
  14. 小学生C++趣味编程 2023 01 09 测试
  15. 一次就让你学懂java运算符
  16. 最优化方法之梯度下降法和牛顿法
  17. 热修复——深入浅出原理与实现
  18. websocket-PacketCapture乱码包解密
  19. NOIP2017旅游(过节)总结
  20. 【北京迅为】瑞芯微系列RK3399六核服务器级开发板接口介绍

热门文章

  1. ajax option请求后无post请求_ThingJS:一种浏览器、服务器和技术的新组合方法——Ajax...
  2. [SpringBoot2]Thymeleaf
  3. 《C++ Primer》1.51节练习
  4. [蓝桥杯2015决赛]五星填数-枚举+数论
  5. 贵州大学计算机专业的导师是谁,贵州大学计算机科学与信息学院导师介绍:王以松...
  6. Block Coordinate Descent
  7. Deeplab 在Qt Creator下编译报错undefined reference to Mat_xxx
  8. P6378 [PA2010] Riddle 2-sat + 前缀和优化建图
  9. Codeforces Round #701 (Div. 2) E. Move and Swap 思维 + dp
  10. P4159 [SCOI2009] 迷路