zoukankan      html  css  js  c++  java
  • 从ReentrantLock实现非公平锁的源码理解AQS中的CLH队列

    虽然前面也看过AQS的文章,并且转载过一篇大佬的分析,但是我觉得他们对于AQS和ReentrantLock部分的源码的分析并不详细,自己理解期来还是有问题,于是自己准备花时间重新梳理下,好了,进入正题。

    第一个线程过来加锁


    我们看的是非公平锁的,这里进入nonfair实现:

    代码如下:

    由于这是第一个线程过来获取锁,所以这里通过cas方式加锁成功,即通过compareAndSetState方法,成功的将state共享变量的值设置为1,并将the owner thread设置为当前线程。这里假设大家已经看过前面连篇关于cas的文章了AQS简单理解入门彻底掌握 AQS
    这里线程1已经加锁成功了,我们假设它暂时是不会释放锁的,因为主要是看aqs内部的队列。

    第二个线程尝试过来加锁

    和第一个线程一样,仍然走进lock方法的非公平实现:

    但是此时由于线程1已经加锁成功,所以cas是失败的,进入到else块的acqure方法里

    这里可以看到,进入acquire方法里,是先调用tryAcquire方法,尝试下,看看能不能加上锁,万一线程1释放了锁呐,这样就不用入队列,我们直接进入到非公平锁的nonfairTryAcquire方法:

    由于我们假设线程1需要占用很久,所以这时tryAcquire()获取锁是失败的,返回为false:

    这里我们先进去这个addWaiter方法:
    在分析这个方法之前,需要先补充下双向链表的知识,要不这里会迷,我们先看官方源码中的注释:

    由于线程1成功获取锁,并没有被阻塞放入CLH队列,且这里由于clh队列是懒加载的,并没有初始化,这时,head和tail指针指向的头尾node节点均为null:
    进入addWaiter:

    进入enq方法,参数为node = new Node(Thread.currentThread(), null);

    这里来张图展示下clh队列的变化:

    方法enq执行完出来后,addWaiter方法也执行结束,并返回创建的node:

    此时回到调用addWaiter方法处,进入acquireQueued方法:

    但是排在队列第二位的线程,如果尝试几次不成功后,也会像后面的线程一样,最后走进shouldParkAfterFailedAcquire()方法:
    这里暂时不分析了,通过上面的分析,已经达到本文的目的,理解clh队列的创建和变化过程。

    艾欧尼亚,昂扬不灭,为了更美好的明天而战(#^.^#)
  • 相关阅读:
    java虚拟机8:内存溢出和内存泄露、并行和并发、Minor GC和Full GC、Client模式和Server模式的区别
    java虚拟机7:垃圾收集器 基于回收算法理论的实现
    java虚拟机5:垃圾回收算法
    java虚拟机1:JVM内存结构
    java虚拟机2:hotspot 对象探究
    java虚拟机4:jvm GC机制回收 判断对象生死 及 方法区永久代回收条件
    java虚拟机3:jvm OutOfMemoryError
    java虚拟机6:hotspot 的算法实现
    JVM调优总结 -Xms -Xmx -Xmn -Xss
    CSS3弹性盒子align-items属性之center垂直居中
  • 原文地址:https://www.cnblogs.com/lovelywcc/p/13997544.html
Copyright © 2011-2022 走看看