`

JUC之ReentrantLock(二)

 
阅读更多

ReentrantLock.unLock():锁的释放

 

    public void unlock() {
        sync.release(1);//AQS
    }

 AbstractQueuedSynchronizer.release()

 

 

    public final boolean release(int arg) {
        if (tryRelease(arg)) {//尝试释放锁,子类实现
            Node h = head;
            if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);//唤醒后继节点
            return true;
        }
        return false;
    }

    若 tryRelease(arg)释放锁成功(state==0);则考虑唤醒AQS中的下一个节点,前提:队列不为空,AQS队列的头结点需要锁(waitStatus!=0),如果头结点需要锁,就开始检测下一个继任节点是否需要锁操作。

waitStatus含义

 

 

ReentrantLock.Sync.tryRelease(int releases)

 

        protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread())//持有锁的线程不是当前线程,抛出异常。(线程锁只有拥有锁的线程才能释放)
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) {//state = 0:表示当前线程已经释放了锁,锁处于空闲状态.因为ReetrantLock可重入,maybe c>0
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }

AbstractQueuedSynchronizer.unparkSuccessor(Node node)

    private void unparkSuccessor(Node node) {
        /*
         * If status is negative (i.e., possibly needing signal) try
         * to clear in anticipation of signalling. It is OK if this
         * fails or if status is changed by waiting thread.
         */
        int ws = node.waitStatus;
        if (ws < 0)//当前node已经释放锁了,状态设置为0
            compareAndSetWaitStatus(node, ws, 0); 

        /*
         * Thread to unpark is held in successor, which is normally
         * just the next node.  But if cancelled or apparently null,
         * traverse backwards from tail to find the actual
         * non-cancelled successor.
         */
        //从头结点的下一个节点开始寻找继任节点,当且仅当继任节点的waitStatus<=0才是有效继任节点,否则将这些waitStatus>0(也就是CANCELLED的节点)从AQS队列中剔除  
        //这里并没有从head->tail开始寻找,而是从tail->head寻找最后一个有效节点。
        //解释在这里 http://www.blogjava.net/xylz/archive/2010/07/08/325540.html#377512
        Node s = node.next;
        if (s == null || s.waitStatus > 0) {
            s = null;
            for (Node t = tail; t != null && t != node; t = t.prev)
                if (t.waitStatus <= 0)
                    s = t;
        }
        if (s != null)
            LockSupport.unpark(s.thread);
    }

 

 

这里再一次把acquireQueued的过程找出来。对比unparkSuccessor,一旦头节点的继任节点被唤醒,那么继任节点就会尝试去获取锁(在acquireQueued中node就是有效的继任节点,p就是唤醒它的头结点),如果成功就会将头结点设置为自身,并且将头结点的前任节点清空,这样前任节点(已经过时了)就可以被GC释放了。

final boolean acquireQueued(final Node node, int arg) {
    try {
        boolean interrupted = false;
        for (;;) {
            final Node p = node.predecessor();
            if (p == head && tryAcquire(arg)) {
                setHead(node);
                p.next = null; // help GC
                return interrupted;
            }
            if (shouldParkAfterFailedAcquire(p, node) &&
                parkAndCheckInterrupt())
                interrupted = true;
        }
    } catch (RuntimeException ex) {
        cancelAcquire(node);
        throw ex;
    }
}

 参考:http://www.blogjava.net/xylz/archive/2010/07/08/325540.html

 

 

分享到:
评论

相关推荐

    java并发编程专题(五)----详解(JUC)ReentrantLock

    Java并发编程中的ReentrantLock是Java并发包(java.util.concurrent,简称JUC)中的一个重要的锁机制,它是Lock接口的一个具体实现,提供了比synchronized更强大的锁定功能和更细粒度的控制。ReentrantLock的主要...

    Java 多线程与并发(11-26)-JUC锁- ReentrantLock详解.pdf

    Java中的ReentrantLock是Java并发包(java.util.concurrent.locks)中的一个高级锁,它是可重入的,意味着一个线程可以多次获取同一锁。在深入ReentrantLock之前,我们首先需要了解Java并发编程的基础,特别是Java...

    JUC线程锁框架

    JUC中的锁机制包括ReentrantLock(可重入锁)、ReadWriteLock(读写锁)等。ReentrantLock相比synchronized具有更细粒度的控制,支持公平性和非公平性,并提供了tryLock()方法来尝试获取锁,以及lockInterruptibly...

    个人学习JUC代码笔记总集

    Java并发编程领域中的JUC(Java Util Concurrency)是一门深奥且实用的技术,它包含在Java的`java.util.concurrent`包中,为多线程编程提供了高效、易用的工具。这个压缩包文件“个人学习JUC代码笔记总集”显然是一...

    艾编程coding老师:JUC 并发编程 + 底层原理.pdf

    JUC也提供了一系列的锁实现,比如ReentrantLock,它提供了比synchronized更灵活的锁控制机制。ReentrantLock支持尝试非阻塞地获取锁、可中断地获取锁以及超时获取锁等多种synchronized关键字所不具备的同步特性。 ...

    尚硅谷Java视频_JUC视频教程

    3. **JUC核心API**:重点学习JUC包中的核心API,如`ReentrantLock`、`Condition`、`CountDownLatch`等。 4. **实战项目**:通过实际项目练习来巩固所学知识,例如实现一个基于线程池的任务调度系统或一个高并发的...

    juc源码视频教程最全

    2. **锁机制**:JUC提供了显式锁ReentrantLock,它比synchronized更灵活,支持公平锁和非公平锁,以及可中断和可重入的特性。此外,还有读写锁ReentrantReadWriteLock,允许多个读取者同时访问,但只允许一个写入者...

    JUC并发编程.md

    - `ReentrantLock`是`Lock`接口的主要实现之一,支持公平锁和非公平锁,以及可中断的锁定机制。 3. **基本售票示例**: - 使用`ReentrantLock`实现售票系统可以有效地控制对资源的访问,避免线程间的冲突。 - ...

    尚硅谷JUC百度云连接

    2. **锁**:除了基本的`synchronized`关键字外,JUC还提供了更灵活的锁机制,如`ReentrantLock`等。 3. **同步器**:如`Semaphore`、`CountDownLatch`、`CyclicBarrier`等,它们可以帮助解决复杂的同步问题。 4. **...

    狂神说JUC代码狂神说JUC代码

    - **ReentrantLock**:可重入锁,功能比synchronized更强大,具有公平性、非公平性选择,以及更细粒度的锁获取和释放控制。 4. **并发容器**: - **ConcurrentHashMap**:线程安全的哈希表,比synchronized的...

    JUC底层讲解,面试可用。

    "JUC底层讲解,面试可用" JUC是Java并发编程的API,java.util.concurrent包名的简写。JUC相关的包有三个:java.util.concurrent、java.util.concurrent.atomic、java.util.concurrent.locks。 并发编程相关概念: ...

    JUC代码收集,java高并发多线程学习

    3. **locks**:此包提供了高级锁定机制,如`ReentrantLock`和`ReadWriteLock`,比内置的`synchronized`关键字更灵活,可以实现更复杂的同步策略。 在学习JUC的过程中,你需要理解以下关键概念: - **线程池**:...

    精心整理的AQS和JUC相关的面试题.pdf【ReentrantLock】

    ⼀、ReentrantLock重⼊锁 1.1&gt; 概述 1.2&gt; 中断响应 lockInterruptibly() 1.3&gt; 锁申请等待限时 tryLock(long time, TimeUnit unit) 1.4&gt; 公平锁和⾮公平锁 1.5&gt; AQS源码解析 ⼆、Condition重⼊锁的搭配类 三、...

    JUC学习笔记 .md

    ### JUC并发编程知识点 #### 1. 进程与线程 - **进程**: 进程是指正在运行中的程序实例。每个进程都有自己独立的内存空间,并且一个进程中可以包含多个线程。例如,当你打开QQ应用时,就启动了一个进程。 - **线程...

    JUC个人笔记1

    在Java并发编程中,"JUC个人笔记1"主要探讨了多线程并发控制的一些核心概念和技巧。首先,遵循高内聚低耦合的原则,将线程的操作与资源类进行解耦,使得代码结构更加清晰,易于维护。在多线程交互中,特别是涉及到`...

    JUC知识点总结(三)ReentrantLock与ReentrantReadWriteLock源码解析

    8. Lock接口 (ReentrantLock 可重入锁) 特性 ReentantLock 继承接口 Lock 并实现了接口中定义的方法, 它是一种可重入锁, 除了能完成 synchronized 所能完成的所有工作外,还提供了诸如可响应中断锁、可轮询锁...

    【小家java】JUC并发编程之:虚假唤醒以及推荐的解决方案.docx

    ### JUC并发编程中的虚假唤醒及其解决方案 #### 一、虚假唤醒的概念与原理 在Java并发编程中,尤其是在处理多线程同步时,一个重要的概念是“虚假唤醒”(Spurious Wakeup)。这是一种较为罕见的现象,但在实际...

    JUC包含线程,线程池,CAS,volatile等底层原理,以及相关问题的解决方式以及相关工具类的使用

    除了volatile,Java还提供了Lock接口及其实现,如ReentrantLock(可重入锁),支持公平/非公平策略,以及ReentrantReadWriteLock(读写锁),允许多个读取者同时访问,但写入者与其他所有线程互斥。 总之,理解和...

Global site tag (gtag.js) - Google Analytics