java 文件锁

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.channels.OverlappingFileLockException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.archermind.nwa.networkagent.log.Logger;

public class TestServlet extends HttpServlet {
    private static Logger logger = Logger
            .getLogger(TestServlet.class.getName());

    protected void service(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        File f = new File("F://kankan//opt.txt");
        RandomAccessFile fi = new RandomAccessFile(f, "rw");
        FileChannel fc = fi.getChannel();
        FileLock fl = null;
        Thread t = Thread.currentThread();
        logger.info(t.getId() + " " + t.getName());
        InetAddress address = InetAddress.getLocalHost();
       
        try {
            try {
                fl = fc.tryLock();
                if (fl == null) {
                    logger.info(address.getHostAddress() + " wait 5 sec for reason (null)!");
                    throw new OverlappingFileLockException();
                }
            } catch (OverlappingFileLockException e) {
                logger.info(address.getHostAddress() + " wait 5 sec once!");
                try {
                    Thread.sleep(5 * 1000);
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
                try {
                    fl = fc.tryLock();
                    if (fl == null) {
                        logger.info(address.getHostAddress() + " wait 5 sec for reason (null)!");
                        throw new OverlappingFileLockException();
                    }
                } catch (OverlappingFileLockException oe) {
                    logger.info(address.getHostAddress()
                            + " cannot get file lock!");
                    throw new OverlappingFileLockException();
                }

            }

            if (fl != null) {
                logger.info(address.getHostAddress() + " start write!");
                fc.position(fc.size());
                fc
                        .write(ByteBuffer
                                .wrap((address.getHostAddress() + " =============1=============== /r/n")
                                        .getBytes()));
                logger.info(address.getHostAddress() + " stop write!");


            }
        } catch (Exception e) {
            logger.info(address.getHostAddress()
                    + " exception or cannot get file lock!");
            response.getWriter().write(address.getHostAddress()
                    + " exception or cannot get file lock!");
            return;
        } finally {

            if (null != fl && fl.isValid()) {
                fl.release();
                logger.info(address.getHostAddress() + " release filelock");
            }

            fc.close();
            fi.close();
        }

    }
}

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

 

通过对 FileChannel 调用 tryLock() lock() ,就可以获得整个文件的 FileLock 。特殊的是, SocketChannel/DatagramChannel/ServerSocketChannel 不需要加锁,因为它们是从单进程实体继承而来,我们通常不在两个进程之间共享网络的 socket

Trylock lock 方法

tryLock() 是非阻塞式的,它设法获取锁,但如果不能获得,例如因为其他一些进程已经持有相同的锁,而且不共享时,它将直接从方法调用返回。

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

对独占锁和共享锁的支持必须由底层的操作系统提供。锁的类型可以通过 FileLock.isShared() 进行查询。另外,我们不能获取缓冲器上的锁,只能是通道上的。

OverlappingFileLockException 锁的作用域

    在某个文件加锁 锁只会作用在此文件上 对其他文件无效

    单个 Java 虚拟机在某个特定文件上所保持的锁定是不重叠的,即同一个 jvm 中不同线程去拿同一文件的锁时,先拿到的获得锁,后获取的无法获得锁, tryLock ()方法不会抛出异常,但获得锁值为 null

       不同 jvm 或者不同操作系统获取同一文件锁时,先拿到的获得锁,后获取的抛出文件重叠锁异常【 OverlappingFileLockException 】。以上是 windows 才会出现如此现象,如果是 linux 会抛出异常:【 java.io.IOException: Permission denied

 

共享锁 独占锁 区别

独占锁 :也称排它锁,如果一个线程获得一个文件的独占锁,那么其它线程就不能再获得同一文件的独占锁或共享锁,直到独占锁被释放。
共享锁 :如果一个线程获得一个文件的共享锁,那么其它线程可以获得同一文件的共享锁或同一文件部分内容的共享锁,但不能获取排它锁

 

a.txt 文件被加独占锁时 其他线程不可读也不可写

a.txt 文件被加共享锁时 其他线程可读也不可写

 

如何获得共享锁

       fc.tryLock(position,size,isShare); 第三个参数为 true 为共享锁

       以下为 api (注意共享锁需要操作支持,如果操作系统不支持共享锁,则自动变更为独占锁)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值