java 文件锁[通俗易懂]

java 文件锁[通俗易懂]今天在分析HDFS数据节点的源码时,了解到在数据节点的文件结构中,当数据节点运行时,${dfs.data.dir}下会有一个名为”in_use.lock”的文件,该文件就是文件锁。文件加锁是JDK1.4引入的一种机制,它允许我们同步访问某个作为共享资源的文件。竞争同一文件的两个线程可能在不同的Java虚拟机上,或者一个是Java线程,另一个是操作系统中的某个本地线程。文件锁对其他的操作系

大家好,又见面了,我是你们的朋友全栈君。

今天在分析HDFS数据节点的源码时,了解到在数据节点的文件结构中,当数据节点运行时,${dfs.data.dir}下会有一个名为”in_use.lock”的文件,该文件就是文件锁。

文件加锁是 JDK1.4 引入的一种机制,它允许我们同步访问某个作为共享资源的文件。竞争同一文件的两个线程可能在不同的 Java 虚拟机上,或者一个是 Java 线程,另一个是操作系统中的某个本地线程。文件锁对其他的操作系统进程是可见的,因为 Java 的文件加锁直接映射到了本地操作系统的加锁工具(通过文件进行加锁)。

在javaNIO中提供了文件锁的功能,这样当一个线程获取文件锁后,才可以操作文件,其他线程是无法操作文件的,要想进行文件锁定的操作,则要使用FileLock类完成,此类的对象需要依靠FileChannel进行实例化。

java文件锁要么独占,要么共享。
共享锁:允许多个线程对文件进行读操作。
独占锁:只允许一个线程进行文件的读写操作

Trylock 与 lock 方法
tryLock(position,size,isShare); 第三个参数为 true 时为共享锁
tryLock() 是非阻塞式的,它设法获取锁,但如果不能获得,例如因为其他一些进程已经持有相同的锁,而且不共享时,抛出文件重叠锁异常【OverlappingFileLockException】。

lock() 是阻塞式的,它要阻塞进程直到锁可以获得,或调用 lock() 的线程中断,或调用 lock() 的通道关闭。

OverlappingFileLockException
单个 Java 虚拟机在某个特定文件上所保持的锁定、不同 jvm 或者不同操作系统获取同一文件锁时,先拿到的获得锁,后获取的抛出文件重叠锁异常【OverlappingFileLockException】。以上是 windows 才会出现如此现象,如果是linux会抛出异常:【java.io.IOException: Permission denied 】

测试代码如下:

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.OverlappingFileLockException;


public class StorageDirectory { 
   
    public static final String STORAGE_FILE_LOCK = "in_use.lock" ;
    File root ; //root directory 
    java.nio.channels.FileLock lock ; //storage lock
    /** * Lock storage to provide exclusive access. * * <p> if locking is supported we guarantee exculsive access to the * storage directory . Otherwise, no guarantee is given * * @throws Exception if locking file */
    public StorageDirectory(File dir){
        this.root = dir ;
    }
    public void lock() throws Exception{
        this.lock = tryLock() ;
        if(lock == null){
            String msg = "Cannot lock storage" + this.root + ". The directory is already locked." ;
            System.err.println(msg) ;
            throw new IOException(msg) ;
        }
    }

    public void unlock() throws IOException{
        if(this.lock == null)
            return ;
        this.lock.release() ;
        lock.channel().close() ;
        lock = null ;
    }
    /** * Attempts to acquire an exclusive lock on the storage * @return A lock object representing the newly-acquired lock or null if * storage is already lockd . * @throws IOException */
    java.nio.channels.FileLock tryLock() throws IOException{
        boolean deletionHookAdded = false ;
        File lockF = new File(root,STORAGE_FILE_LOCK) ;

        //如果没有文件
        if(!lockF.exists()){
            lockF.deleteOnExit() ;
            deletionHookAdded = true ;
        }

        RandomAccessFile file = new RandomAccessFile(lockF,"rws") ;
        java.nio.channels.FileLock res = null ;
        try{
            res = file.getChannel().tryLock() ;
        }catch(OverlappingFileLockException oe){
            file.close() ;
            return null ;
        }catch(IOException e){
            System.err.println("Cannot create lock on " + lockF) ;
            file.close() ;
            throw e ;
        }

        if(res !=null && !deletionHookAdded){
            //if the file existed prior to our startup, we didn't
            //call deleteOnExit above. But since we successfully locked
            //the dir , we can take care of cleaning it up 
            lockF.deleteOnExit() ;
        }
        return res ;
    }

}

测试类

import java.io.File;
import java.io.IOException;


class Operation implements Runnable{
    private StorageDirectory sd ;
    public Operation(StorageDirectory sd){
        this.sd = sd ;
    }
    public void run() {
        try {
            System.out.println("文件加锁");
            sd.lock() ;
        } catch (Exception e) {
            System.out.println("文件加锁失败") ;
            return ;
        }
        try {
            Thread.currentThread().sleep(1000) ;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally{
            try {
                System.out.println("释放文件锁");
                sd.unlock() ;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

}

public class Main { 
   

    /** * @param args */
    public static void main(String[] args) throws Exception{
        File dir = new File("G:\\eclipse-SDK-4.2.2-win32-x86_64\\workspace\\FileLock") ;
        StorageDirectory sd1 = new StorageDirectory(dir) ;
        new Thread(new Operation(sd1)).start() ;
    // Thread.sleep(2000) ;//注释掉文件加锁失败,解开注释文件加锁成功
        StorageDirectory sd2 = new StorageDirectory(dir) ;
        new Thread(new Operation(sd2)).start() ;
    }

}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/153487.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 线程创建的四种方式

    线程创建的四种方式java中创建线程的四种方法以及区别Java使用Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例。Java可以用四种方式来创建线程,如下所示:1)继承Thread类创建线程2)实现Runnable接口创建线程3)使用Callable和Future创建线程4)使用线程池例如用Executor框架下面让我们分别来看看这四种创建线程的方法。–…

    2022年5月3日
  • 方差及常见分布的方差计算与推导公式_超几何分布的期望和方差

    方差及常见分布的方差计算与推导公式_超几何分布的期望和方差1.介绍方差定义和性质2.离散型随机变量(01分布,二项分布,泊松分布,几何分布,超几何分布)和连续型随机变量(均匀分布,指数分布,正态分布)分布的方差计算以及推导过程,并汇总形成表格,方便查阅和记录

    2022年9月17日
  • 课程设计酒店管理系统_管理系统课程设计

    课程设计酒店管理系统_管理系统课程设计1.题目要求•顾客入住、退房•房间预订•换房处理•续住管理•折扣2.架构选择:B/SB/S结构,即Browser/Server(浏览器/服务器)结构,是随着Internet技术的兴起,对C/S结构的一种变化或者改进的结构。在这种结构下,用户界面完全通过WWW浏览器实现。3.语言选择:PythonhtmlccsJavaScripthtml…

    2022年9月15日
  • FragmentPagerAdapter刷新notifyDataSetChanged无效

    FragmentPagerAdapter刷新notifyDataSetChanged无效网络上会提到pageadapter的刷新方案如下代码: 复写pageradapter的getItemPosition方法设置tag为POSITION_NONE意思是没有找到child要求重新加载。@Override publicintgetItemPosition(Objectobject){   returnPOSITION_NONE; } 结果

    2022年6月24日
  • vim 关键字搜索_vim中查找某个字符命令

    vim 关键字搜索_vim中查找某个字符命令linux系统里的vim是编辑文本的命令,在vi里查找相应关键字的方法如下:例如搜索the写法:/the+回车/+关键字,回车即可。此为从文档当前位置向下查找关键字,按n键查找关键字下一个位置; ?+关键字,回车即可。此为从文档挡圈位置向上查找关键字,按n键向上查找关键字;…

    2022年9月2日
  • #ZipLib可以用于闭源软件

    #ZipLib可以用于闭源软件一直对各开源协议理解得不够透彻,对#ZipLib说的这段话:[quote]helibraryisreleasedundertheGPLwiththefollowingexception:Linkingthislibrarystaticallyordynamicallywithothermodulesismakingacombin…

    2022年7月26日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号