zoukankan      html  css  js  c++  java
  • ReentrantLock源码解析3优先响应中断的lockInterruptibly

    • ReentrantLock.lockInterruptibly允许在等待时由其它线程调用等待线程的Thread.interrupt方法来中断等待线程的等待而直接返回,这时不用获取锁,而会抛出一个InterruptedException。
    • ReentrantLock.lock方法不允许Thread.interrupt中断,即使检测到Thread.isInterrupted,一样会继续尝试获取锁,失败则继续休眠。只是在最后获取锁成功后再把当前线程置为interrupted状态。

    具体实现如下:

    1.lock

    Lock在第一次获取锁失败后会走:

        public final void acquire(int arg) {
            if (!tryAcquire(arg) &&
                acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
                //中断当前线程
                selfInterrupt();
        }
    View Code

    addWaiter封装Node节点插入到队列尾部,acquireQueued负责队列的挂起、出队、是否中断

        final boolean acquireQueued(final Node node, int arg) {
            boolean failed = true;
            try {
                boolean interrupted = false;
                for (;;) {
                    final Node p = node.predecessor();
                    if (p == head && tryAcquire(arg)) {
                        setHead(node);
                        p.next = null; // help GC
                        failed = false;
                        //在独占锁后,才返回中断标识
                        return interrupted;
                    }
                    //shouldParkAfterFailedAcquire:判断线程可否安全挂起
                    //parkAndCheckInterrupt:挂起线程并返回当时中断标识Thread.interrupted()
                    if (shouldParkAfterFailedAcquire(p, node) &&
                        parkAndCheckInterrupt())
                        //当parkAndCheckInterrupt返回中断标识为true时修改interrupted
                        interrupted = true;
                }
            } finally {
                if (failed)
                    cancelAcquire(node);
            }
        }
    View Code

    2. lockInterruptibly

    lockInterruptibly会直接走下面程序

        public final void acquireInterruptibly(int arg)
                throws InterruptedException {
            if (Thread.interrupted())
                throw new InterruptedException();
            if (!tryAcquire(arg))
                //没有得到独占锁后
                doAcquireInterruptibly(arg);
        }
    View Code

    doAcquireInterruptibly

        private void doAcquireInterruptibly(int arg)
            throws InterruptedException {
            final Node node = addWaiter(Node.EXCLUSIVE);
            boolean failed = true;
            try {
                for (;;) {
                    final Node p = node.predecessor();
                    if (p == head && tryAcquire(arg)) {
                        setHead(node);
                        p.next = null; // help GC
                        failed = false;
                        //这里没有中断标识
                        //lock和lockInterruptibly区别就是对中断的处理方式 
                        return;
                    }
                    //shouldParkAfterFailedAcquire:判断线程可否安全挂起
                    //parkAndCheckInterrupt:挂起线程并返回当时中断标识Thread.interrupted()
                    if (shouldParkAfterFailedAcquire(p, node) &&
                        parkAndCheckInterrupt())
                        //当parkAndCheckInterrupt返回中断标识为true时立即抛出异常中断线程
                        throw new InterruptedException();
                }
            } finally {
                if (failed)
                    cancelAcquire(node);
            }
        }
    View Code
  • 相关阅读:
    arcgis api 3.x for js 入门开发系列八聚合效果(附源码下载)
    arcgis api 3.x for js 入门开发系列七图层控制(附源码下载)
    arcgis api 3.x for js 入门开发系列六地图分屏对比(附源码下载)
    arcgis api 3.x for js 入门开发系列五地图态势标绘(附源码下载)
    arcgis api 3.x for js 入门开发系列四地图查询(附源码下载)
    Java里面获取当前服务器的IP地址
    Flutter at Google I/O 2018
    Modbus RTU 协议使用汇总
    plsql 创建表空间、用户、赋予权限
    Oracle:ODP.NET Managed 小试牛刀
  • 原文地址:https://www.cnblogs.com/yifanSJ/p/8942549.html
Copyright © 2011-2022 走看看