目录

linux文件锁flock

NIO文件锁FileLock

java程序怎么在一个电脑上只启动一次,只开一个进程

文件锁可以是shared(共享锁)或者exclusive(排他锁)。不是所有的平台都以同一种方式实现文件锁,不同的操作系统可能不同,同一操作系统上的不同文件系统也可能不同。有些操作系统只提供协同锁,有些只提供强制锁,有些则都提供。linux锁见《linux文件锁flock》的详细说明。

文件锁是以文件为单位的,不是以通道,也不是线程。所以文件锁不适合同一个多个线程访问的情形。如果一个线程获得了给定文件的排他锁,第二个线程请求打开了一个新的channel,请求获得排他锁,请求会被批准。但如果这两个线程运行在不同的JVM中,第二个线程会阻塞,因为锁往往是根据进程来进行裁决,而不是线程。锁工作于一个文件,而不是单独的文件处理器或是通道。

如果你需要控制多个线程之间的同步,你可能需要实现自己的轻量级的锁,内存映射文件可能是个适合的选择。

public abstract class FileChannel extends AbstractChannel implements ByteChannel, GatheringByteChannel, ScatteringByteChannel {

  public final FileLock lock()
public abstract FileLock lock (long position, long size, boolean shared) public final FileLock tryLock()
public abstract FileLock tryLock(long position, long size, boolean shared)
}

先看带参数的lock方法,获得给定区域的锁,自position开始,size大小,第三个布尔参数代表是锁是否共享。锁的区域并不受到文件大小的限制,锁可以超过文件的大小,也就是说在一段区域被写入数据之前锁住,是可行的。相反的,如果文件的大小超出了锁的限制,也就将不受到锁的限制。不带参数的lock方法,等效于
fileChannel.lock(0L,Long.MAX_VALUE, false);
如果你的请求是有效的,那么lock方法就会生效,但是要等待前一个锁(如果存在的话)释放。

tryLock方法是lock方法非阻塞的变种,功能和lock相似,但是如果不能立刻获得锁的话,tryLock会返回null。从创建开始,直到调用FileLock的release方法,FileLock对象都是有效的。可以通过isValid方法测试。一个锁是否有效可能会改变,但锁的位置,大小,是否共享,是不变的。

你可以通过isShared判断锁是否为共享锁,如果内在的文件系统操作系统不支持共享,那么这个方法总是会返回false,就算你传递true作为构造函数也一样。FileLock是线程安全的,多个线程可以通过一个FileLock进行操作。尽管FileLock对象和一个Channel相关,但是其实锁是和内在的文件联系的。这有可能造成冲突,也有可能死锁,如果你完成了操作而没有释放锁的话。一个典型的代码如下所示:

FileLock lock = fileChannel.lock();
try{
<perform read/write/whatever on channel>
} catch (IOException e) {
<handle unexcepted exception>
} finally {
lock.release();
}

下面是一个使用FileLock进行操作的例子

package com.dxz.nettydemo.websocket;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
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("d:\\temp\\logfile.txt", true).getChannel();
RandomAccessFile raf = new RandomAccessFile("d:\\temp\\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();
System.out.println(Thread.currentThread().getName() + "get lock = " + lock);
} 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();
}
}
} try {
Thread.sleep(50000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

多启动几个,观察跨进程间的文件锁作用了。

看看获取lock和释放lock的源码:FileChannelImpl.java

http://www.docjar.com/html/api/sun/nio/ch/FileChannelImpl.java.html

      public FileLock tryLock(long position, long size, boolean shared)
1008 throws IOException
1009 {
1010 ensureOpen();
1011 if (shared && !readable)
1012 throw new NonReadableChannelException();
1013 if (!shared && !writable)
1014 throw new NonWritableChannelException();
1015 FileLockImpl fli = new FileLockImpl(this, position, size, shared);
1016 FileLockTable flt = fileLockTable();
1017 flt.add(fli);
1018 int result;
1019
1020 int ti = threads.add();
1021 try {
1022 try {
1023 ensureOpen();
1024 result = nd.lock(fd, false, position, size, shared);
1025 } catch (IOException e) {
1026 flt.remove(fli);
1027 throw e;
1028 }
1029 if (result == FileDispatcher.NO_LOCK) {
1030 flt.remove(fli);
1031 return null;
1032 }
1033 if (result == FileDispatcher.RET_EX_LOCK) {
1034 assert shared;
1035 FileLockImpl fli2 = new FileLockImpl(this, position, size,
1036 false);
1037 flt.replace(fli, fli2);
1038 return fli2;
1039 }
1040 return fli;
1041 } finally {
1042 threads.remove(ti);
1043 }
1044 }
1045
1046 void release(FileLockImpl fli) throws IOException {
1047 int ti = threads.add();
1048 try {
1049 ensureOpen();
1050 nd.release(fd, fli.position(), fli.size());
1051 } finally {
1052 threads.remove(ti);
1053 }
1054 assert fileLockTable != null;
1055 fileLockTable.remove(fli);
1056 }

NIO文件锁FileLock的更多相关文章

  1. [转载] 文件锁(Filelock)与锁定映射文件部分内容

    转载自http://jiangzhengjun.iteye.com/blog/517677 文件锁 JDK 1.4引入了文件加锁机制,允许我们同步访问一个共享文件,不过,竞争同一文件的两个线程有可能在 ...

  2. 文件锁FileLock

    1.文件锁的定义 FileLock是文件锁,进程锁,用于进程间并发,控制不同程序(JVM)对同一文件的并发访问. FileLock是java 1.4 版本后出现的一个类,它可以通过对一个可写文件(w) ...

  3. NIO之FileChannel类的理解和使用

    文章链接:http://blog.csdn.net/qq_16628781/article/details/70532307 知识点: FileChannel类及方法理解: 普通输入输出流复制文件: ...

  4. java程序怎么在一个电脑上只启动一次,只开一个进程

    目录 <linux文件锁flock> <NIO文件锁FileLock> <java程序怎么在一个电脑上只启动一次,只开一个进程> 方案1: 单进程程序可以用端口绑定 ...

  5. JAVA基础知识之NIO——Buffer.Channel,Charset,Channel文件锁

    NIO机制 NIO即NEW IO的意思,是JDK1.4提供的针对旧IO体系进行改进之后的IO,新增了许多新类,放在java.nio包下,并对java.io下许多类进行了修改,以便使用与nio. 在ja ...

  6. JAVA NIO FileChannel 内存映射文件

      文件通道总是阻塞式的. 文件通道不能创建,只能通过(RandomAccessFile.FileInputStream.FileOutputStream)getChannel()获得,具有与File ...

  7. Java使用FileLock实现Java进程互斥锁

    原理:JDK的nio包中FileLock实现类似Linux fcntl的文件锁, 可使文件被进程互斥访问.  借助此功能, 可以实现强大的Java进程互斥锁, 从而在应用层面保证同一时间只有惟一的Ja ...

  8. Java NIO之通道

    一.前言 前面学习了缓冲区的相关知识点,接下来学习通道. 二.通道 2.1 层次结构图 对于通道的类层次结构如下图所示. 其中,Channel是所有类的父类,其定义了通道的基本操作.从 Channel ...

  9. 海纳百川而来的一篇相当全面的Java NIO教程

    目录 零.NIO包 一.Java NIO Channel通道 Channel的实现(Channel Implementations) Channel的基础示例(Basic Channel Exampl ...

随机推荐

  1. java基本数据类型的范围

    System.out.println("BYTE MAX_VALUE = " + Byte.MAX_VALUE); System.out.println("BYTE MI ...

  2. 《DSP using MATLAB》Problem 5.27

    代码: %% +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %% Outp ...

  3. 把oracle数据库恢复到某个时间点或者某个scn

    alter session set nls_date_format='yyyymmdd hh24:mi:ss'; select sysdate from dual; conn dbauser/1234 ...

  4. oracle服务器重启后无法进入系统,登录系统时提示model is unknow

    这个是因为安装oracle时,修改了一些系统参数,导致开机异常 在选择系统列表那里直接按e,进入系统开机配置 大概在倒数第二行,也就是有utf8那行,添加init=/bin/sh 然后ctrl+x重启 ...

  5. 原生js实现ajax用于简单的签到或登录

    <script> function createStandardXHR() {     try {         return new window.XMLHttpRequest(); ...

  6. 【转载】Win10打开U盘提示“文件或目录损坏无法读取”怎么办?

    以下文转载至系统之家 网址:http://www.xitongzhijia.net/xtjc/20190314/152334.html (PS:暂未亲测) Win10打开U盘提示“文件或目录损坏无法读 ...

  7. mysql全备和增量备份以及恢复过程(percona工具)

    实验环境 系统环境,内核版本和xtrabackup工具版本 [root@linux-node1 mysql]# cat /etc/redhat-release CentOS Linux release ...

  8. Zabbix-2.4-安装-3

      zabbix自动注册简单介绍---创建自动注册的actions   怎么把1000台机器加zabbix里 zabbix提供了网络发现和自动注册2个功能,发现有机器连过来,给它加个模板 如果是win ...

  9. TypeScript 之 声明文件的结构

    https://www.tslang.cn/docs/handbook/declaration-files/library-structures.html 模块化库 一些库只能工作在模块加载器的环境下 ...

  10. C# 文件上传和下载

    一.   在Form中一定要将encType设为"multipart/form-data": <form id="WebForm3" method=&qu ...