FileLock 多进程文件锁
FileLock是文件锁,它能保证同一时间只有一个进程(程序)能够修改它,或者都只可以读,这样就解决了多进程间的同步文件,保证了安全性。但是需要注意的是,它进程级别的,不是线程级别的,他可以解决多个进程并发访问同一个文件的问题,但是它不适用于控制同一个进程中多个线程对一个文件的访问。这也是为什么它叫做 多进程文件锁,而不是 多线程文件锁。
FileLock一般都是从FileChannel 中获取,FileChannel 提供了三个方法用以获取 FileLock。
- lock() 是阻塞式的,它要阻塞进程直到锁可以获得,或调用
lock()的线程中断,或调用lock()的通道关闭。 - tryLock()是非阻塞式的,它设法获取锁,但如果不能获得,例如因为其他一些进程已经持有相同的锁,而且不共享时,它将直接从方法调用返回。
position:锁定文件中的开始位置
size:锁定文件中的内容长度
shared:是否使用共享锁。true为共享锁;false为独占锁。
/**
* 先运行
* @throws Exception
*/
@Test
public void FileWriteTest() throws Exception {
RandomAccessFile randomAccessFile = new RandomAccessFile("D:\\temp\\filelock.txt", "rw");
FileChannel fileChannel = randomAccessFile.getChannel();
System.out.println("进程 1 开始写内容:" + LocalTime.now());
for (int i = 1; i <= 10; i++) {
randomAccessFile.writeUTF("VipSoft_" + i);
System.out.println("writeChars:" + i);
// 等待两秒
TimeUnit.SECONDS.sleep(2);
}
System.out.println("进程 1 完成写内容:" + LocalTime.now());
fileChannel.close();
randomAccessFile.close();
} /**
* 再运行,看读出文件大小的变化
* @throws Exception
*/
@Test
public void FileReadTest() throws Exception {
RandomAccessFile randomAccessFile = new RandomAccessFile("D:\\temp\\filelock.txt", "rw");
FileChannel fileChannel = randomAccessFile.getChannel();
System.out.println("开始读文件的时间:" + LocalTime.now()); for (int i = 0; i < 10; i++) {
// FileWriteTest() 运行后,运行 FileReadTest(),发现文件大小在变。说明文件在一边读一边写
System.out.println("文件大小为:" + randomAccessFile.length());
// 这里等待 1 秒
TimeUnit.SECONDS.sleep(1);
} System.out.println("结束读文件的时间:" + LocalTime.now());
fileChannel.close();
randomAccessFile.close();
}
使用文件锁,使用后,只能等锁释放掉以后,另一个进程才能对期进行操作
/**
* 先运行
* @throws Exception
*/
@Test
public void FileWriteTest() throws Exception {
RandomAccessFile randomAccessFile = new RandomAccessFile("D:\\temp\\filelock.txt", "rw");
FileChannel fileChannel = randomAccessFile.getChannel();
// 这里是独占锁
FileLock fileLock = fileChannel.lock();
System.out.println("进程 1 开始写内容:" + LocalTime.now());
for (int i = 1; i <= 10; i++) {
randomAccessFile.writeUTF("VipSoft_" + i);
System.out.println("writeChars:" + i);
// 等待两秒
TimeUnit.SECONDS.sleep(2);
}
System.out.println("进程 1 完成写内容:" + LocalTime.now());
// 完成后要释放掉锁
fileLock.release();
fileChannel.close();
randomAccessFile.close();
} /**
* 再运行,看读出文件大小的变化
* @throws Exception
*/
@Test
public void FileReadTest() throws Exception {
RandomAccessFile randomAccessFile = new RandomAccessFile("D:\\temp\\filelock.txt", "rw");
FileChannel fileChannel = randomAccessFile.getChannel();
// 这里是独占锁
FileLock fileLock = fileChannel.lock();
System.out.println("开始读文件的时间:" + LocalTime.now()); for (int i = 0; i < 10; i++) {
// FileWriteTest() 运行后,运行 FileReadTest(),发现文件大小在变。说明文件在一边读一边写
System.out.println("文件大小为:" + randomAccessFile.length());
// 这里等待 1 秒
TimeUnit.SECONDS.sleep(1);
} System.out.println("结束读文件的时间:" + LocalTime.now());
// 完成后要释放掉锁
fileLock.release();
fileChannel.close();
randomAccessFile.close();
}
同进程不同线程进行文件读写
FileLock是不适用同一进程不同线程之间文件的访问。因为你根本无法在一个进程中不同线程同时对一个文件进行加锁操作,如果线程1对文件进行了加锁操作,这时线程2也来进行加锁操作的话,则会直接抛出异常:java.nio.channels.OverlappingFileLockException
import org.junit.Test; import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.time.LocalTime;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; public class FileLockTest {
@Test
public void RunnableTest() throws InterruptedException {
Runner1 runner1 = new Runner1();
Runner2 runner2 = new Runner2();
Thread thread1 = new Thread(runner1);
Thread thread2 = new Thread(runner2);
thread1.start();
thread2.start();
System.out.print("阻塞当前线程,直到倒数计数器倒数到0");
new CountDownLatch(1).await();
} class Runner1 implements Runnable { // 实现了Runnable接口,jdk就知道这个类是一个线程
public void run() {
try {
FileWriteTest();
} catch (Exception e) {
e.printStackTrace();
}
}
} class Runner2 implements Runnable { // 实现了Runnable接口,jdk就知道这个类是一个线程
public void run() {
try {
FileReadTest();
} catch (Exception e) {
e.printStackTrace();
}
}
} /**
* 先运行
* @throws Exception
*/
public void FileWriteTest() throws Exception {
RandomAccessFile randomAccessFile = new RandomAccessFile("D:\\temp\\filelock.txt", "rw");
FileChannel fileChannel = randomAccessFile.getChannel();
// 这里是独占锁
FileLock fileLock = fileChannel.lock();
System.out.println("进程 1 开始写内容:" + LocalTime.now());
for (int i = 1; i <= 10; i++) {
randomAccessFile.writeUTF("VipSoft_" + i);
System.out.println("writeChars:" + i);
// 等待两秒
TimeUnit.SECONDS.sleep(2);
}
System.out.println("进程 1 完成写内容:" + LocalTime.now());
// 完成后要释放掉锁
fileLock.release();
fileChannel.close();
randomAccessFile.close();
} /**
* 再运行,看读出文件大小的变化
* @throws Exception
*/
@Test
public void FileReadTest() throws Exception {
RandomAccessFile randomAccessFile = new RandomAccessFile("D:\\temp\\filelock.txt", "rw");
FileChannel fileChannel = randomAccessFile.getChannel();
// 这里是独占锁
FileLock fileLock = fileChannel.lock();
System.out.println("开始读文件的时间:" + LocalTime.now()); for (int i = 0; i < 10; i++) {
// FileWriteTest() 运行后,运行 FileReadTest(),发现文件大小在变。说明文件在一边读一边写
System.out.println("文件大小为:" + randomAccessFile.length());
// 这里等待 1 秒
TimeUnit.SECONDS.sleep(1);
} System.out.println("结束读文件的时间:" + LocalTime.now());
// 完成后要释放掉锁
fileLock.release();
fileChannel.close();
randomAccessFile.close();
}
}
可以通过另外一种方式来规避程序异常,如下:
FileLock fileLock;
while (true){
try{
fileLock = fileChannel.tryLock();
break;
} catch (Exception e) {
System.out.println("这里是 FileWriteTest ,其他线程已经获取该文件锁了,当前线程休眠 2 秒再获取");
TimeUnit.SECONDS.sleep(2);
}
}
完整DEMO如下
package org.apache.rocketmq.store; import org.junit.Test; import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.time.LocalTime;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; public class FileLockTest { @Test
public void RunnableTest() throws InterruptedException {
Runner1 runner1 = new Runner1();
Runner2 runner2 = new Runner2();
Thread thread1 = new Thread(runner1);
Thread thread2 = new Thread(runner2);
thread1.start();
thread2.start();
System.out.print("阻塞当前线程,直到倒数计数器倒数到0");
new CountDownLatch(1).await();
} class Runner1 implements Runnable {
public void run() {
try {
FileWriteTest();
} catch (Exception e) {
e.printStackTrace();
}
}
} class Runner2 implements Runnable {
public void run() {
try {
FileReadTest();
} catch (Exception e) {
e.printStackTrace();
}
}
} /**
* 先运行
* @throws Exception
*/
public void FileWriteTest() throws Exception {
RandomAccessFile randomAccessFile = new RandomAccessFile("D:\\temp\\filelock.txt", "rw");
FileChannel fileChannel = randomAccessFile.getChannel();
// 这里是独占锁
FileLock fileLock;
while (true){
try{
fileLock = fileChannel.tryLock();
break;
} catch (Exception e) {
System.out.println("这里是 FileWriteTest ,其他线程已经获取该文件锁了,当前线程休眠 2 秒再获取");
TimeUnit.SECONDS.sleep(2);
}
} System.out.println("进程 1 开始写内容:" + LocalTime.now());
for (int i = 1; i <= 10; i++) {
randomAccessFile.writeUTF("VipSoft_" + i);
System.out.println("writeChars:" + i);
// 等待两秒
TimeUnit.SECONDS.sleep(2);
}
System.out.println("进程 1 完成写内容:" + LocalTime.now());
// 完成后要释放掉锁
fileLock.release();
fileChannel.close();
randomAccessFile.close();
} /**
* 再运行,看读出文件大小的变化
* @throws Exception
*/
@Test
public void FileReadTest() throws Exception {
RandomAccessFile randomAccessFile = new RandomAccessFile("D:\\temp\\filelock.txt", "rw");
FileChannel fileChannel = randomAccessFile.getChannel();
// 这里是独占锁
FileLock fileLock;
while (true){
try{
fileLock = fileChannel.tryLock();
break;
} catch (Exception e) {
System.out.println("这里是 FileReadTest,其他线程已经获取该文件锁了,当前线程休眠 2 秒再获取");
TimeUnit.SECONDS.sleep(2);
}
}
System.out.println("开始读文件的时间:" + LocalTime.now()); for (int i = 0; i < 10; i++) {
// FileWriteTest() 运行后,运行 FileReadTest(),发现文件大小在变。说明文件在一边读一边写
System.out.println("文件大小为:" + randomAccessFile.length());
// 这里等待 1 秒
TimeUnit.SECONDS.sleep(1);
} System.out.println("结束读文件的时间:" + LocalTime.now());
// 完成后要释放掉锁
fileLock.release();
fileChannel.close();
randomAccessFile.close();
}
}
FileLock 多进程文件锁的更多相关文章
- Java NIO中的FileLock(文件锁)
FileLock,文件锁. 文件锁在OS中很常见,如果多个程序同时访问.修改同一个文件,很容易因为文件数据不同步而出现问题.给文件加一个锁,同一时间,只能有一个程序修改此文件,或者程序都只能读此文件, ...
- 【死磕NIO】— 跨进程文件锁:FileLock
大家好,我是大明哥,一个专注于[死磕 Java]系列创作的程序员. [死磕 Java ]系列为作者「chenssy」 倾情打造的 Java 系列文章,深入分析 Java 相关技术核心原理及源码 死磕 ...
- 文件锁FileLock
1.文件锁的定义 FileLock是文件锁,进程锁,用于进程间并发,控制不同程序(JVM)对同一文件的并发访问. FileLock是java 1.4 版本后出现的一个类,它可以通过对一个可写文件(w) ...
- Java进程间通信学习
转自:https://www.iteye.com/blog/polim-1278435 进程间通信的主要方法有:(1)管道(Pipe):管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共 ...
- 《JAVA程序设计》_第六周学习总结
一.本周学习内容 1.内部类--7.1知识 在一个类的内部定义的类成为内部类,包含内部类的类叫做外嵌类 内部类和外嵌类的关系 外嵌类的成员变量在内部类中仍然有效,内部类也可调用外嵌类中的方法 内部类的 ...
- 20175212童皓桢 《Java程序设计》第六周学习总结
20175212童皓桢 <Java程序设计>第六周学习总结 教材学习内容总结 第七章 内部类与异常类 1.内部类 Java支持在一个类中定义另一个类,这样的类称作内部类,包含内部类的类称为 ...
- 海纳百川而来的一篇相当全面的Java NIO教程
目录 零.NIO包 一.Java NIO Channel通道 Channel的实现(Channel Implementations) Channel的基础示例(Basic Channel Exampl ...
- 20165237 2017-2018-2 《Java程序设计》第5周学习总结
20165237 2017-2018-2 <Java程序设计>第5周学习总结 教材学习内容总结 1.内部类:在一个类中定义另一个类:外嵌类:包含内部类的类. 2.内部类的类体中不能声明类变 ...
- 20175314 《Java程序设计》第六周学习总结
20175314 <Java程序设计>第六周学习总结 教材学习内容总结 第七章:内部类与异常类 内部类:内部类就是在一个类中再定义一个类,这个在类中定义的类就叫做内部类,而包含内部类的类叫 ...
- java程序怎么在一个电脑上只启动一次,只开一个进程
目录 <linux文件锁flock> <NIO文件锁FileLock> <java程序怎么在一个电脑上只启动一次,只开一个进程> 方案1: 单进程程序可以用端口绑定 ...
随机推荐
- 「译文」Google SRE 二十年的经验教训
️URL: https://sre.google/resources/practices-and-processes/twenty-years-of-sre-lessons-learned/ ✍️Au ...
- 记录jdk17相对于jdk8增加的一下主要语法糖和新特性
jdk17 发布已经好久了,作为java的长期支持版本,引入了许多有趣且实用的新特性.这些特性不仅提高了开发效率,还增强了语言的表现力和安全性.并且是SpringBoot 3.0以后版本的硬性要求,之 ...
- go并发 - channel
概述 并发编程是利用多核心能力,提升程序性能,而多线程之间需要相互协作.共享资源.线程安全等.任何并发模型都要解决线程间通讯问题,毫不夸张的说线程通讯是并发编程的主要问题.go使用著名的CSP(Com ...
- 痞子衡嵌入式:在IAR开发环境下手动拷贝自定义程序段到RAM中执行的方法
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是IAR下手动拷贝自定义程序段到RAM中执行的方法. 在痞子衡旧文 <IAR下RT-Thread工程自定义函数段重定向失效分析> ...
- python3使用libpcap给ESL命令添加日志记录
操作系统 :CentOS 7.6_x64 FreeSWITCH版本 :1.10.9 python版本:3.9.12 libpcap版本:1.11.0b7 FreeSWITCH的ESL模块用起来很方 ...
- 时间复杂度为 O(n^2) 的排序算法
对于小规模数据,我们可以选用时间复杂度为 O(n2) 的排序算法.因为时间复杂度并不代表实际代码的执行时间,它省去了低阶.系数和常数,仅代表的增长趋势,所以在小规模数据情况下, O(n2) 的排序算法 ...
- Go语言数组与切片学习总结
一.数组 数组的定义:相同类型的数据集合 go语言中数组的索引从0开始 没有赋值的数值型数组,默认值为0 数组一旦被创建,它的大小就是不可改变的 (1)声明数组与打印 var 变量名 [大小]变量类型 ...
- 实例讲解Python 解析JSON实现主机管理
本文分享自华为云社区<Python 解析JSON实现主机管理>,作者: LyShark. JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它以易 ...
- Bert-vits2新版本V2.1英文模型本地训练以及中英文混合推理(mix)
中英文混合输出是文本转语音(TTS)项目中很常见的需求场景,尤其在技术文章或者技术视频领域里,其中文文本中一定会夹杂着海量的英文单词,我们当然不希望AI口播只会念中文,Bert-vits2老版本(2. ...
- CoreFlex框架发布 `0.1.1`
CoreFlex框架发布 0.1.1 框架描述 CoreFlex是一个支持.NET 6,.NET 7,.NET 8的快速开发框架,也提供MasaFramework相关框架的集成提供更多功能模块, 集成 ...