Java 进程间文件锁FileLock详解
转载自 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详解相关推荐
- Java并发编程最佳实例详解系列
Java并发编程最佳实例详解系列: Java并发编程(一)线程定义.状态和属性 Java并发编程(一)线程定义.状态和属性 线程是指程序在执行过程中,能够执行程序代码的一个执行单元.在java语言中, ...
- 【Java基础】HashMap原理详解
[Java基础]HashMap原理详解 HashMap的实现 1. 数组 2.线性链表 3.红黑树 3.1概述 3.2性质 4.HashMap扩容死锁 5. BATJ一线大厂技术栈 HashMap的实 ...
- 《Java和Android开发实战详解》——1.2节Java基础知识
本节书摘来自异步社区<Java和Android开发实战详解>一书中的第1章,第1.2节Java基础知识,作者 陈会安,更多章节内容可以访问云栖社区"异步社区"公众号查看 ...
- Java中的Runtime类详解
Java中的Runtime类详解 1.类注释 /**Every Java application has a single instance of class Runtime that allows ...
- Java多线程之volatile详解
Java多线程之volatile详解 目录: 什么是volatile? JMM内存模型之可见性 volatile三大特性之一:保证可见性 volatile三大特性之二:不保证原子性 volatile三 ...
- [java] 虚拟机(JVM)底层结构详解[转]
[java] 虚拟机(JVM)底层结构详解[转] 本文来自:曹胜欢博客专栏.转载请注明出处:http://blog.csdn.net/csh624366188 在以前的博客里面,我们介绍了在java领 ...
- Linux进程管理工具 Supervisor详解
介绍 Supervisor安装与配置(linux/unix进程管理工具) Supervisor(http://supervisord.org)是用Python开发的一个client/server服务, ...
- Java使用Jco连接sap详解
SAP的R/3系统与Java平台一样有着许多类似的技术理念,以及同样广泛的企业级用户,但是它们完全是两个不同的世界.当用户面临流程 或者数据整合方面的需求的时候,就迫切需要一种高效的方式,在R/3系统 ...
- Java虚拟机之垃圾回收详解一
Java虚拟机之垃圾回收详解一 Java技术和JVM(Java虚拟机) 一.Java技术概述: Java是一门编程语言,是一种计算平台,是SUN公司于1995年首次发布.它是Java程序的技术基础,这 ...
最新文章
- shell getopt 获取参数
- 1040. Longest Symmetric String (25)
- 只能在微信浏览器打开的链接,如何查看源码
- OMG,隔壁老王竟然是个GEEK !
- mysql5.7.24免安装版配置_mysql5.7.20免安装版配置方法图文教程
- c语言中执行一次的函数once,iOS只执行一次的方法
- Qt Creator快捷键大全
- 软件测试——软件开发过程
- java实现微信支付
- websocket使用指南
- 微信 - 微信语音转发好友 / 朋友圈方法
- 微信登录(官方指导)
- 数据基础---数据可视化
- 小学生C++趣味编程 2023 01 09 测试
- 一次就让你学懂java运算符
- 最优化方法之梯度下降法和牛顿法
- 热修复——深入浅出原理与实现
- websocket-PacketCapture乱码包解密
- NOIP2017旅游(过节)总结
- 【北京迅为】瑞芯微系列RK3399六核服务器级开发板接口介绍
热门文章
- ajax option请求后无post请求_ThingJS:一种浏览器、服务器和技术的新组合方法——Ajax...
- [SpringBoot2]Thymeleaf
- 《C++ Primer》1.51节练习
- [蓝桥杯2015决赛]五星填数-枚举+数论
- 贵州大学计算机专业的导师是谁,贵州大学计算机科学与信息学院导师介绍:王以松...
- Block Coordinate Descent
- Deeplab 在Qt Creator下编译报错undefined reference to Mat_xxx
- P6378 [PA2010] Riddle 2-sat + 前缀和优化建图
- Codeforces Round #701 (Div. 2) E. Move and Swap 思维 + dp
- P4159 [SCOI2009] 迷路