目录

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. 神坑,使用gcc对opencv重编译

    工具 cmake-3.9.1 opencv-3.3.0  gcc-6.3.0 前几天为了装eclipse的CDT,把minggw里的make改了,今天突然想学opencv,可是只找到了vc版本,千辛万 ...

  2. cifX驱动安装及SYCON.net的使用

    编程之路刚刚开始,错误难免,希望大家能够指出. cifX驱动安装及SYCON.net的使用 说明: 简单描述运行cifX的示例之前需要进行的准备,具体的主从站设置请自行查看DVD中的文档. 关于cif ...

  3. Linux配置浮动IP

    在高可用集群环境中,一般都需要使用浮动IP来实现web高可用(High Availability). 浮动IP的概念以及为什么需要浮动IP请参考:https://blog.csdn.net/readi ...

  4. git pull refusing to merge unrelated histories

    1. 简介 最近的项目开发环境我换到实验室的机器上了,毕竟是台式机,速度杠杠的.于是出现了一个问题,台式机上面的代码我笔记上的代码同步的问题.于是想到了Git这个强大的工具.关于git的简介我就不说了 ...

  5. mysql新建用户在本地无法登录

    新建了一个mysql用户,但是无法在本地登录,即使已经授权任一ip都可以登录,甚至特地写清楚localhost登录,还是不行,情况如下 [root@localhost zabbix-release-3 ...

  6. Java和C++的区别杂记

    1.java中的作用域描述符(类比于C++是通过"."来实现,Java中"类名.静态成员名",C++中"类名::静态成员名" 2.java中 ...

  7. MySQL Export--导出数据

    =========================================================== SELECT INTO OUTFILE语法格式: SELECT [columns ...

  8. code自动补全

    软件安装完成后,第一次一定要使用这种方式创建文件,才会有代码自动提示: https://blog.csdn.net/haibin8473/article/details/79113650 https: ...

  9. cJSON学习笔记 续集

    0.前言     本文试图说明怎样使用CJSON构造各种各样的JSON数据包.在前段时间已经写过一篇cJSON的文章,所以本文成为"续集".     [相关博文]     [前端学 ...

  10. Dev TextEdit 输入提示

    TextEdit.Properties.NullValuePromptShowForEmptyValue = true; TextEdit.Properties.NullValuePrompt = “ ...