JAVA 文件锁 FileLock

概述

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

共享锁、独占锁

  • 共享锁:允许多个线程进行文件的读取操作
  • 独占锁: 只允许一个线程进行文件的读/写操作

获得 FileLock

通过 NIO 的 API 首先获取文件的 FileChannel ,然后可以通过 FileChannel 以下4中方式获取FileLock。

1. 通过lock() 获取 FileLock,获取文件的独占锁

public final FileLock lock() throws IOException {
    return lock(0L, Long.MAX_VALUE, false);
}

默认锁定整个文件,并设置为独占锁。

2. 通过改方法可以锁定文件的部分数据,并支持设置共享锁。

public FileLock lock(long position, long size, boolean shared) throws IOException{
  ......
}
  • position:锁定文件中的开始位置
  • size: 锁定文件中的内容长度
  • shared: 是否使用共享锁。true为共享锁定;false为独占锁定。

一些不支持共享锁的操作系统,将自动将共享锁改成排它锁。可以通过调用isShared()方法来检测获得的是什么类型的锁。

3. 试图获取文件独占锁

public final FileLock tryLock() throws IOException {
    return tryLock(0L, Long.MAX_VALUE, false);
}

如果获取不到锁,则返回null。而不阻塞当前线程,等待获取锁。

4. 通过改方法可以尝试获得文件的部分数据的锁,并支持设置共享锁。

public abstract FileLock tryLock(long position, long size, boolean shared) throws IOException{
    ......
}

参数同上2。 如果获取不到锁,则返回null。

使用场景

  1. 如果多个应用部署到同一台机器上,并且同时操作同一份数据(数据库中或文件中的数据),可以使用FileLock充当分布式锁。

示例

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;

public class FileLockTest {  
  
    public static void main(String[] args){  
        FileLock lock = null;  
        try (FileChannel channel = new FileOutputStream("d:\\file.lock",true).getChannel()){  
            lock = channel.lock();//无参lock()为独占锁
            //lock = channel.lock(0L, channel.size(), true);    //共享锁
            //其它逻辑
            ......
        } catch (FileNotFoundException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally {  
            if (lock != null) {  
                try {  
                    lock.release();  
                    lock = null;  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
        }  
    }  
}  
  1. 对于一个只读文件通过任意方式加锁时会报NonWritableChannelException异常
  2. 无参lock()默认为独占锁,不会报NonReadableChannelException异常,因为独占就是为了写
  3. 有参lock()为共享锁,所谓的共享也只能读共享,写是独占的,共享锁控制的代码只能是读操作,当有写冲突时会报NonWritableChannelException异常

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Python爬虫与算法进阶

Python函数超时,用装饰器解决

我们在自定义一个函数后,会调用这个函数来完成我们想要的功能。 就拿爬虫来举例,你发送请求,服务器给你响应,但是有可能服务器没有给你任何数据,无论是他识别了爬虫、...

3312
来自专栏

socket读写返回值的处理

在调用socket读写函数read(),write()时,都会有返回值。如果没有正确处理返回值,就可能引入一些问题 总结了以下几点 1当read()或者writ...

2495
来自专栏友弟技术工作室

Requests库详解

requests(爬虫系列之一) 由于最近工作中,与同事对接模拟手机浏览器进行广告模拟跳转。又一次接触用到爬虫的知识,以前用过urllib + bs4 + se...

3859
来自专栏指尖下的Android

Android4.4运行过程中闪退java.lang.NoClassDefFoundError

上周五项目测试时发现一个奇怪的Bug,项目中依赖了一个第三方框架,但是在android4.0-4.4.4之间的系统中运行会直接闪退,抛出错误异常为java.la...

1232
来自专栏Java与Android技术栈

Scala学习笔记(一)mac下安装ScalaIDE选择总结

过年前就定(chui)下了目(niu)标(bi),今年要学习一下Scala和Spark赶一下潮流。谁叫落后就要挨打呢,程序员只能不停的学习。一个语言,学习的第一...

1392
来自专栏Java帮帮-微信公众号-技术文章全总结

request;response 对象

response ? 1. response简介 response的类型为HttpServletResponse,它是Servlet的service()方法的参...

3637
来自专栏企鹅号快讯

Python的线程

本文是基于Py2.X 线程 多任务可以由多进程完成,也可以由一个进程内的多线程完成。 我们前面提到了进程是由若干线程组成的,一个进程至少有一个线程。 多线程类似...

2348
来自专栏python3

python3--队列Queue,管道Pipe,进程之间的数据共享,进程池Pool,回调函数callback

既打印了主进程put的值,也打印了子进程put的值,在进程中使用队列可以完成双向通信

5291
来自专栏Java架构

Java并发之Condition的实现分析

回忆 synchronized 关键字,它配合 Object 的 wait()、notify() 系列方法可以实现等待/通知模式。

782
来自专栏炸天帮5

win32进程概念之句柄表,以及内核对象.

我们知道.我们使用CreateProcess 的时候会返回一个进程句柄.以及线程句柄. 其实在调用CreateProcess的时候.内核中会新建一个EPROCE...

911

扫码关注云+社区

领取腾讯云代金券