ReentrantLock 公平锁和非公平锁加锁和解锁源码分析(简述)

Windows11配置WSL2支持代理上网 说起来本来这个功能我也不需要的,只是最近突然有个需求就顺便研究了下,WSL2默认的网络方式是NAT,即WSL2的网卡本身是虚拟网卡,通过以太网或WIFI的地址转换来上互联网,我试了下是不能直接走代理的,最近比较忙没具体研究,但是我用另一种方式实现了,下面介绍给需要的人。注意:这个方法只能是WIndows11系统,WIndows10系统上的WSL2缺少了一项功能导致不可用。1、方法总体没什么难度,NAT方式暂时没研究透,后续有时间再研究2、WIndows10系统不支持mirrored,暂时需要另辟蹊径。 阅读详情
- title: ReentrantLock 公平锁和非公平锁加锁和解锁源码分析(简述)
- date: 2021/8/16

一、ReentrantLock

ReentantLock 继承接口 Lock 并实现了接口中定义的方法,他是一种可重入锁,除了能完成
synchronized 所能完成的所有工作外,还提供了诸如可响应中断锁、可轮询锁请求、定时锁等避免多线程死锁的方法。

1. 构造函数

    private final Sync sync;
    //...
    /**
     * Creates an instance of {@code ReentrantLock}.
     * This is equivalent to using {@code ReentrantLock(false)}.
     */
    public ReentrantLock() {
        sync = new NonfairSync();
    }

    /**
     * Creates an instance of {@code ReentrantLock} with the
     * given fairness policy.
     *
     * @param fair {@code true} if this lock should use a fair ordering policy
     */
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }

无参和有参构造函数,用于构造公平锁或非公平锁。

二、ReentrantLock 公平锁的加锁(lock)过程

参考示例代码:

class ReentrantLockExample {
    int           a    = 0;
    ReentrantLock lock = new ReentrantLock();

    public void writer() {
        lock.lock(); //获取锁
        try {
            a++;
        } finally {
            lock.unlock(); //释放锁
        }
    }

    public void reader() {
        lock.lock(); //获取锁
        try {
            int i = a;
            //……
        } finally {
            lock.unlock(); //释放锁
        }
    }
}

1.1 调用ReentrantLock中的lock

//ReentrantLock.java ReentrantLock
    /**
     * Acquires the lock.
     *
     * <p>Acquires the lock if it is not held by another thread and returns
     * immediately, setting the lock hold count to one.
     *
     * <p>If the current thread already holds the lock then the hold
     * count is incremented by one and the method returns immediately.
     *
     * <p>If the lock is held by another thread then the
     * current thread becomes disabled for thread scheduling
     * purposes and lies dormant until the lock has been acquired,
     * at which time the lock hold count is set to one.
     */
     /**
      * 获取锁。
      *
      * <p>如果没有被其他线程持有则获取锁并返回
      * 立即,将锁定保持计数设置为 1。
      *
      * <p>如果当前线程已经持有锁,则持有
      * count 加一,方法立即返回。
      *
      * <p>如果锁被另一个线程持有,那么
      * 当前线程被禁用以进行线程调度
      * 目的并处于休眠状态,直到获得锁,
      * 此时锁定保持计数设置为 1。
      */
    public void lock() {
        sync.lock();
    }

1.2 调用Sync中的抽象方法lock,具体实现由子类完成,这里是非公平锁

//ReentrantLock.java Sync
    abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = -5179523762034025860L;

        /**
         * Performs {@link Lock#lock}. The main reason for subclassing
         * is to allow fast path for nonfair version.
         */
        abstract void lock();

1.3 调用NonfairSync中的 lock;

//ReentrantLock.java NonfairSync
    /**
     * Sync object for non-fair locks
     */
    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;

        /**
         * Performs lock.  Try immediate barge, backing up to normal
         * acquire on failure.
         */
        final void lock() {
            //首先尝试进行CAS操作,将state值从0改为1
            if (compareAndSetState(0, 1))
                //如果CAS成功,设置exclusiveOwnerThread为当前变量
                //获取锁成功说明:1.state从0变为1;(从无竞争资源变为独占资源) 
                //2. 此锁的exclusiveOwnerThread 为当前线程
                setExclusiveOwnerThread(Thread.currentThread());
            else
                //如果CAS失败,说明有其它的线程在抢占这个锁资源
                acquire(1);
        }

//AbstractOwnableSynchronizer.java AbstractOwnableSynchronizer   
    
    /**
     * The current owner of exclusive mode synchronization.
     */
    private transient Thread exclusiveOwnerThread;

    /**
     * Sets the thread that currently owns exclusive access.
     * A {@code null} argument indicates that no thread owns access.
     * This method does not otherwise impose any synchronization or
     * {@code volatile} field accesses.
     * @param thread the owner thread
     */
    protected final void setExclusiveOwnerThread(Thread thread) {
        exclusiveOwnerThread = thread;
    }
        
 //AbstractQueuedSynchronizer.java AbstractQueuedSynchronizer
    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }
  • 首先执行 compareAndSetState(0, 1) ,尝试进行CAS操作,将state值从0改为1;

    • 如果CAS成功,调用 setExclusiveOwnerThread(Thread.currentThread()) ,设置exclusiveOwnerThread为当前变量;

      获取锁成功说明:

      1. state从0变为1;(从无竞争资源变为独占资源) ;

      2. 此锁的 exclusiveOwnerThread 为当前线程

    • 如果CAS失败,说明有其它的线程在抢占这个锁资源,执行acquire(1);

1.3.1 acquire 方法:

 //AbstractQueuedSynchronizer.java AbstractQueuedSynchronizer
    /**
     * Acquires in exclusive mode, ignoring interrupts.  Implemented
     * by invoking at least once {@link #tryAcquire},
     * returning on success.  Otherwise the thread is queued, possibly
     * repeatedly blocking and unblocking, invoking {@link
     * #tryAcquire} until success.  This method can be used
     * to implement method {@link Lock#lock}.
     *
     * @param arg the acquire argument.  This value is conveyed to
     *        {@link #tryAcquire} but is otherwise uninterpreted and
     *        can represent anything you like.
     */
    public final void acquire(int arg) {
        if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }
1.3.1.1 tryAcquire
//ReentranLock.java NonFairSync
    protected final boolean tryAcquire(int acquires) {
        return nonfairTryAcquire(acquires);
    }
        /**
         * Performs non-fair tryLock.  tryAcquire is implemented in
         * subclasses, but both need nonfair try for trylock method.
         */
        final boolean nonfairTryAcquire(int acquires) {
            //获取当前线程
            final Thread current = Thread.currentThread();
            int c = getState();
            //如果c是0,锁处于空闲状态,使用CAS获取
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {
                    //如果CAS成功,设置当前线程是锁的持有者
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            //如果当前线程是锁的持有者,这是ReentrantLock可重入的原因;
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                //可以看出源码设计者的周到,考虑到了锁溢出的情况
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                //将当前线程持有的锁+1
                setState(nextc);
                return true;
            }
            return false;
        }
1.3.1.2 acquireQueued
1.3.1.2.1 addWaiter()

addWaiter():将当前线程插入至队尾,返回在等待队列中的节点(就是处理了它的前驱后继)。

    private Node addWaiter(Node mode) {
        //把当前线程封装为node,指定资源访问模式
        Node node = new Node(Thread.currentThread(), mode);
        // Try the fast path of enq; backup to full enq on failure
        Node pred = tail;
        //如果tail不为空,把node插入末尾
        if (pred != null) {
            node.prev = pred;
            //此时可能有其他线程插入,所以使用CAS重新判断tail
            if (compareAndSetTail(pred, node)) {
                pred.next = node;
                return node;
            }
        }
        //如果tail为空,说明队列还没有初始化,执行enq()
        enq(node);
        return node;
    }

enq():将节点插入队尾,失败则自旋,直到成功。

    private Node enq(final Node node) {
        for (;;) {
            Node t = tail;
            //虽然tail==null才会执行本方法
            //但是可能刚好有其他线程插入,会导致
            //之前的判断失效,所以重新判断tail是否为空
            //队尾为空,说明队列中没有节点
            //初始化头尾节点
            if (t == null) { 
                if (compareAndSetHead(new Node()))
                    //初始化完成后,接着走下一个循环,
                    //直到node正常插入尾部
                    tail = head;
            } else {
                //下面就是链表的正常插入操作了
                node.prev = t;
                if (compareAndSetTail(t, node)) {
                    t.next = node;
                    return t;
                }
            }
        }
    }
1.3.1.2.2 acquireQueued:

该函数表示将已经在队列中的node(每个线程对应一个node加到等待队列中,具体以后分析)尝试去获取锁否则挂起

    final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                //自旋
                final Node p = node.predecessor(); //获得该node
        /*
         * 如果前置节点是head,表示之前的节点就是正在运行的线程,表示是第一个排队的
         * (一般讲队列中第一个是正在处理的,可以想象买票的过程,第一个人是正在买票(处理中),第二个才是真正排队的人);
         * 那么再去tryAcquire尝试获取锁,如果获取成功,说明此时前置线程已经运行结束,则将head设置为当前节点返回
         */
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    // help GC,将前置节点移出队列,这样就没有指针指向它,可以被gc回收
                    p.next = null; // help GC
                    failed = false;
                    //返回false表示不能被打断,意思是没有被挂起,也就是获得到了锁
                    return interrupted;
                }
        /* shouldParkAfterFailedAcquire将前置node设置为需要被挂起,
         *注意这里的waitStatus是针对当前节点来说的,
         * 即是前置node的ws指的是下一个节点的状态
         */
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }
1.3.1.2.2.1 shouldParkAfterFailedAcquire()

shouldParkAfterFailedAcquire():判断当前节点是否应该被挂起。下面涉及到的等待状态,这里再回忆一下,CANCELLED =1,SIGNAL =-1,CONDITION = -2,PROPAGATE = -3,0

    private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
        int ws = pred.waitStatus;
        if (ws == Node.SIGNAL)
            //前驱节点的状态是SIGNAL,说明前驱节点释放资源后会通知自己
            //此时当前节点可以安全的park(),因此返回true
            return true;
        if (ws > 0) {
            //前驱节点的状态是CANCLLED,说明前置节点已经放弃获取资源了
            //此时一直往前找,直到找到最近的一个处于正常等待状态的节点
            //并排在它后面,返回false
            do {
                node.prev = pred = pred.prev;
            } while (pred.waitStatus > 0);
            pred.next = node;
        } else {
            //前驱节点的状态是0或PROPGATE,则利用CAS将前置节点的状态置
            //为SIGNAL,让它释放资源后通知自己
            //如果前置节点刚释放资源,状态就不是SIGNAL了,这时就会失败
            // 返回false
            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
        }
        return false;
    }

parkAndCheckInterrupt():若确定有必要park,才会执行此方法。

    private final boolean parkAndCheckInterrupt() {
        //使用LockSupport,挂起当前线程
        LockSupport.park(this);
        return Thread.interrupted();
    }
1.3.1.3 selfInterrupt

selfInterrupt():对当前线程产生一个中断请求。能走到这个方法,说明acquireQueued()返回true,就进行自我中断。

    static void selfInterrupt() {
        Thread.currentThread().interrupt();
    }

到这里,获取资源的流程就走完了。

##1.4 获取非公平锁总结

  1. 在NonSync中的lock函数CAS尝试获取锁;

  2. 如果CAS失败,**tryAcquire()**尝试获取资源,该函数是一个钩子函数,在非公平锁中是nonfairTryAcquire();

    在nonfairTryAcquire中,会如果当前锁的状态是空闲的,进行CAS尝试获取锁,如果成功返回true,失败返回false; 否则,判断当前线程是否拥有该锁,进行一个可重入的操作,否则返回false;

  3. 如果tryAcquire返回false, 调用acquireQueued(addWaiter(Node.EXCLUSIVE), arg)),首先执行的是addWaiter函数;

    在addWaiter中,将当前线程插入至队尾(CAS操作),返回在等待队列中的节点(就是处理了它的前驱后继),如果tail为空或CAS失败,执行enq():将节点插入队尾,失败则自旋,直到成功。

    然后执行acquireQueued函数,进行一个自旋操作,获取前面的节点,判断是否是头节点head,如果是调用tryAcquire函数再次进行CAS获取锁和可重入的判断,如果成功,然后help GC,将前置节点移出队列,返回interrupted;否则,执行shouldParkAfterFailedAcquire(pred,node),如果返回true,再执行park,如果返回true,interrupted = true,继续自旋;

    shouldParkAfterFailedAcquire(pred,node):

    首先获取前驱节点的状态,

    如果前驱节点的状态是SIGNAL,说明前驱节点释放资源后会通知自己,此时当前节点可以安全的park(),因此返回true;

    如果前驱节点的状态是CANCLLED(1),说明前置节点已经放弃获取资源了,此时一直往前找,直到找到最近的一个处于正常等待状态的节点,将当前节点并排在它后面,返回false;

    如果前驱节点的状态是0或PROPGATE,则利用CAS将前置节点的状态置为SIGNAL,让它释放资源后通知自己,然后返回false;

    parkAndCheckInterrupt():若确定有必要park,才会执行此方法。使用LockSupport,挂起当前线程,并会返回当前线程是否处于中断状态;

  4. 如果acquireQueued返回true,执行selfInterrupt():对当前线程产生一个中断请求。能走到这个方法,说明acquireQueued()返回true,就进行自我中断。

就此,加锁过程完成;

三、ReentrantLock 非公平锁和非公平锁的解锁(unlock)过程

二者的解锁是相同的;

    public void unlock() {
        sync.release(1);
    }
    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也是一个钩子函数:尝试释放锁,彻底释放后返回true

//ReentrantLock.java ReentrantLock
        protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
            //释放锁必须保证当前线程是锁的持有者
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            //如果释放后状态值为0,则彻底释放,持有者置空
            if (c == 0) {
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }

在释放锁的最后写volatile变量 state;

unparkSuccessor():尝试找到下一位继承人,就是确定下一个获取资源的线程,唤醒指定节点的后继节点。

    private void unparkSuccessor(Node node) {
        //如果状态为负说明是除CANCEL以外的状态,
        //尝试在等待信号时清除。
        int ws = node.waitStatus;
        if (ws < 0)
            compareAndSetWaitStatus(node, ws, 0);

        Node s = node.next;
        //下一个节点为空或CANCELLED状态
        //则从队尾往前找,找到正常状态的节点作为之后的继承人
        //也就是下一个能拿到资源的节点
        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);
    }

四、ReentrantLock 公平锁的加锁(lock)过程

//ReentrantLock.java FairLock
       final void lock() {
            acquire(1);
        }

公平锁和非公平锁获取锁只有在钩子函数tryAcquire的实现不同,和非公平锁相比,增加了一个判断当前节点是否是头节点;

        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                //判断等待队列中是否有前驱节点,没有则尝试获取锁
                //hasQueuedPredecessors()返回false,表示没有前驱节点,当前线程就是头节点
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            //实现可重入
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }

boolean hasQueuedPredecessors():判断当前线程是否位于CLH同步队列中的第一个。如果是则返回flase,否则返回true。

    public final boolean hasQueuedPredecessors() {
        //判断当前节点在等待队列中是否为头节点的后继节点(头节点不存储数据),
        //如果不是,则说明有线程比当前线程更早的请求资源,
        //根据公平性,当前线程请求资源失败。
        //如果当前节点没有前驱节点的话,才有做后面的逻辑判断的必要性
        Node t = tail; // Read fields in reverse initialization order
        Node h = head;
        Node s;
        return h != t &&
            ((s = h.next) == null || s.thread != Thread.currentThread());
    }

参考连接:

  1. AQS源码详细解读 - 知乎 (zhihu.com)
  2. ReentrantLock源码详细解读 - 知乎 (zhihu.com)
AUTOSAR进阶图解==>AUTOSAR_SWS_ADCDriver 本文深入解析了AUTOSAR ADC Driver的架构设计和技术实现。主要内容包括:1)ADC Driver在AUTOSAR分层架构中的定位及核心功能;2)详细的模块架构设计,涵盖初始化管理、组转换管理、优先级处理等核心子组件;3)全面的配置模型说明,包括主配置类、通用配置、通道配置等关键数据结构;4)状态机机制和操作序列分析。通过分层设计和标准化接口,ADC Driver实现了硬件抽象和软件解耦,提供了良好的可移植性和可维护性。 阅读详情

相关推荐

脑机接口最新发展动态报告 (2024-2025)

脑机接口动态

高山 4106

二探ReentrantLock非公平锁的加解锁过程

ReentrantLock reentrantLock = new ReentrantLock(); reentrantLock.lock(); //... reentrantLock.unlock(); ①java.util.concurrent.locks.ReentrantLock#lock public void lock() { //具体的sync有公平和非公平(默认)两种 sync.lock(); } ②java.util.

cj_eryue的博客 368

CST局部网格加密实战:从基础设置到Meshgroup高效管理

本文详细解析了CST电磁仿真软件中的局部网格加密技术,重点介绍Meshgroup功能的高效管理方法。通过平行板电容等实战案例,阐述从基础设置到多级加密策略的完整流程,帮助用户精准提升关键区域仿真精度,同时优化计算资源使用效率。

grafana6viz的博客 694

Lock公平锁与非公平锁的源码分析(以ReentrantLock为例)

一、类的结构简介 Lock是一个接口,ReentrantLock则是这个接口的一个实现类,在ReentrantLock中有一个抽象内部类Sync,ReentrantLock中所有方法的实现均在这个抽象内部类中。 而这个抽象内部类Sync又可以分为两个子类,分别为NonfairSync和FairSync。 具体的结构图如下: 在ReentrantLock的构造方法中,需要传入一个boolean型参数fair,内部类Sync将根据这个参数的值来创建对应的子类。 ...

weixin_44105468的博客 1284

SAP OBYC自动过账全解析:从BSX到WRX的会计科目配置指南

本文深入解析SAP OBYC自动过账功能,从BSX到WRX的会计科目配置全流程,涵盖评估分组代码、事务码和评估类等核心概念。通过实战案例展示如何实现库存变动到财务过账的自动化流转,提升企业财务数据的准确性和效率。

weixin_29239279的博客 419

热更新方案 HybridCLR 学习教程 |(一)原理及准备工作

前面文章介绍了热更新相关的知识,包括使用xLua实现热更新实战等 那本文就来介绍一下 热更新方案 HybridCLR(代号wolong,原huatuo)和基本使用方法。 若是想了解更多关于HybridCLR的东西也可以去 官网 详细查阅。

努力前行,总会成为自己心中的那道光 2万+

公平性锁和非公平锁:ReentrantLock源码解析

在Java中为了保证代码同步时的安全问题,通常会使用线程同步机制,前面讲过了使用重量级锁Synchronized来保证线程安全,虽然Java对Synchronized做了优化,性能上已经有了大的提升,但是仍然会推荐使用Lock,也就是今天介绍的另外一种保证线程安全的方式:可重入锁 使用 可重入锁(ReentrantLock)的使用比较简单,而且非常灵活 我们只需要new一个ReentrantLoc...

博客 804

Qt 5.14安装(配置MSVC 2017)

本文主要介绍Qt MSVC的安装,VS2017.

ifeng12358的博客 3710

ReentrantLock非公平锁与公平锁源码解析

这篇从源码入手,深入了解ReentrantLock的非公平锁和公平锁的实现过程。之前已经写过ReentrantLock-基础,ReentrantLock的实现基于AQS,所以还需要先了解同步器AbstractQueueSynchronizer。 非公平锁 ReentrantLock lock = new ReentrantLock(false); try { lock.l...

diaog的博客 258

STC单片机使用FatFs文件系统读取SD卡指定文件内容

STC单片机使用FatFs文件系统读取SD卡指定文件内容

perseverance51博客 2745

STM32F103待机模式原理与低功耗实战指南

待机模式是嵌入式系统实现超低功耗的核心机制,其本质是通过切断内核域电源(VDD/VDDA)实现微安级静态电流,区别于睡眠/停止模式的状态保持特性。原理上依赖电源域隔离、WKUP引脚事件唤醒与RTC备份域协同,技术价值在于支撑电池供电设备长达数年续航。典型应用场景包括物联网传感器节点、智能电表、便携医疗设备等对功耗极度敏感的终端。工程落地需严格遵循GPIO模拟输入配置、唤醒标志清除、备份域解锁等关键步骤,避免因漏电或误唤醒导致实测电流超标。本文以STM32F103为例,深入解析待机模式的硬件基础与HAL库实现

weixin_32999557的博客 66

ReentrantLock【公平锁和非公平锁】的【加锁和解锁】全过程

声明: ReentrantLock的公平锁和非公平锁都是【独占锁】; 加锁和解锁流程图

qq_43783527的博客 355

7、复杂分布式水文模型的两阶段代理参数校准框架

本文提出了一种针对复杂分布式水文模型的两阶段代理参数校准框架,旨在解决可变入渗能力模型(VIC)在参数校准过程中计算成本高、耗时长的问题。该框架结合AdaBoost与反向传播神经网络(BPNN)构建高精度代理模型,并引入ε-NSGA II多目标优化算法加速搜索最优参数集。通过在兰江流域和湘江流域的实验验证,该方法在校准效率上提升了约20倍,同时保持了高模拟精度(NSE接近1,Bias接近0)。框架采用两阶段设计:第一阶段(SM-I)快速筛选关键参数范围,第二阶段(SM-II)进行高精度预测,显著减少了无效计

apple5的专栏 86

ReentrantLock 加锁,解锁,加锁中断,公平锁,非公平锁源码分析

ReentrantLock 基本使用 ReentrantLock lock = new ReentrantLock(true); // false 或无参非公平锁,true 公平锁 lock.lock(); // 获取锁,如果获锁失败,线程进入阻塞(休眠) lock.tryLock(); // 尝试获取锁,失败不会阻塞 lock.lockInterruptibly(); //获取锁,如果获锁失败,线程进入阻塞,支持获锁阻塞的中断退出 lock.unlock(); // 释放锁 Reentran

JohnZ的专栏 425

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

【ReentrantLock源码分析】非公平锁的加锁和解锁

非公平锁去加锁的时候会尝试去抢俩次,也可以说三次,因为第三次抢锁条件是当当前节点的前一个节点是头节点的时候,即是空的时候,这个时候才会去再次尝试抢锁,也就是后面前面没人排队购票了,然后我正好去购票了。 前俩次抢锁一个是在加锁的时候就会进行抢锁,没成功的话,调用 tryAcquire 的时候又会去进行一次抢锁,这里还包括了可重入操作,即更新 state+=1(arg) 否则最后进入队列然后将线程挂起。

qq_63691275的博客 380

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

java锁ReentrantLock的源码分析

java锁ReentrantLock的源码分析简单的函数介绍加锁过程猜测加锁流程源码分析tryAcquireaddWaiterenqacquireQueued解锁流程tryLock,和lockInterruptibly总结 简单的函数介绍 声明锁对象,构造函数默认不传是创建非公平锁,传true是创建一个公平锁 ReentrantLock lock = new ReentrantLock(true); 重入锁,lock和unlock成对出现, lock.lock(); lock.unlock(); 尝试加

u013510360的专栏 383

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

ReentrantLock

首先简单介绍一个ReentrantLock这个锁。 ReentrantLock是java中可重入锁的一个实现,一次只能有一个线程持有锁,即就是所谓的独占锁。ReentrantLock包含三个内部类:Sync、NonfairSync、FairSync,通过构造函数的参数参数fair决定,true为公平锁实现,false为非公平锁实现。默认是非公平锁。 (为什么默认是非公平锁?因为非公平锁的执行效...

禾露悠悠摇的博客 179

ReentrantLock的源码阅读

ReentrantLock的源码阅读

cssweb_sh的博客 215

9. Java JUC源码分析系列笔记-ReentrantLock

1.1. Java JUC源码分析系列笔记-JMM模型之先谈硬件2.2. Java JUC源码分析系列笔记-JMM模型之再谈JMM3.3. Java JUC源码分析系列笔记-Synchronized4.4. Java JUC源码分析系列笔记-锁的优化5.5. Java JUC源码分析系列笔记-volatile6.6. Java JUC源码分析系列笔记-CAS7.7. Java JUC源码分析系列笔记-AQS8.8. Java JUC源码分析系列笔记-手写AQS9.

weixin_36915902的博客 74

【深度长文】聊一聊 Java AbstractQueuedSynchronizer 以及在 ReentrantLock 中的应用

一篇深入分析 Java AQS 和 ReentrantLock 的技术博客,包含丰富的图片以及代码注释,钻研同步工具的底层源码。

wzz2333的博客 1214

并发编程7-Lock锁系列 ReentrantLock

目录 前言 加锁目的 Lock 锁的继承体系 Lock 顶层接口分析 可重入锁ReentrantLock ReentrantLock 公平锁和非公平锁是什么?有什么区别? ReentrantLock源码分析 类的继承关系 类的内部类 Sync类 NonfairSync类 FairSyn类 类的属性 类的构造函数 核心函数分析 应用示例: 参考推荐: 前言 加锁目的 序列化访问临界资源,即同一时刻只能有一个线程访问临界资源(同步互斥访问) 首先明确:Lock

ming13849012515的博客 900

Java源码分析系列笔记-6.ReentrantLock

1.Java源码分析系列笔记-1.JMM模型之先谈硬件2.Java源码分析系列笔记-1.JMM模型之再谈JMM3.Java源码分析系列笔记-4.Java源码分析系列笔记-2.锁的优化5.Java源码分析系列笔记-3.volatile6.Java源码分析系列笔记-4.CAS7.Java源码分析系列笔记-5.AQS8.Java源码分析系列笔记-5.手写AQS9.Java源码分析系列笔记-10.Java源码分析系列笔记-7.Lock之Condition收起目录。

weixin_42533751的博客 138

并发能力夯实:ReentrantLock 源码分析!

文章内容已经收录在,欢迎订阅专栏!从原理出发,直击面试难点,实现更高维度的降维打击!

qq_45260619的博客 1117

【JUC并发编程】7 ReentrantLock锁机制原理/源码分析

Lock实现原理? ReentrantLock实现原理? ReentrantLock源码分析?

健身变秃,coding变强 942
上一篇: 乐观锁 VS 悲观锁(简述)
下一篇: 获得Local IP Address (C++实现)
long Rookie
博客等级 码龄6年 378粉丝 47原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值