• ReentrantLock源码阅读


    默认构造方法初始化同步器为非公平同步器

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

     lock()方法调用的是sync的lock()方法

        public void lock() {
            sync.lock();
        }
    
        final void lock() {
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }

    如果将state从0改为1成功,那么将属性exclusiveOwnerThread改为当前线程,代表获得锁成功

        protected final boolean compareAndSetState(int expect, int update) {
            // See below for intrinsics setup to support this
            return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
        }
        
        protected final void setExclusiveOwnerThread(Thread thread) {
            exclusiveOwnerThread = thread;
        }

    修改失败走acquire,参数arg为1

    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

    三步走

    1.tryAcquire调用的是nonfairTryAcquire

    protected final boolean tryAcquire(int acquires) {
        return nonfairTryAcquire(acquires);
    }
    
    //aquire为1
    final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState();
      //这个逻辑什么时候会走?其他线程第一次抢锁失败,然后恰好获得锁的线程释放了锁?
    if (c == 0) { if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } }
      //获得锁的线程重入会走这个逻辑
    else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; }

    2.又一次抢锁失败,且不是当前线程重入,tryAcquire返回false,走下一步逻辑acquireQueued(addWaiter(Node.EXCLUSIVE), arg))

    2.1 addWaiter(Node.EXCLUSIVE)  (将新节点插入尾节点之后,如果尾节点为空,初始化一个新节点,没有线程,既是头也是尾,返回新节点有thread没有addwaiter)

    private Node addWaiter(Node mode) {
        Node node = new Node(Thread.currentThread(), mode);
        // Try the fast path of enq; backup to full enq on failure
        //如果有尾节点,将当前节点插入尾节点之后(可能其他线程也在做此事,失败了没关系下一步会处理)
        Node pred = tail;
        if (pred != null) {
            node.prev = pred;
            if (compareAndSetTail(pred, node)) {
                pred.next = node;
                return node;
            }
        }
        enq(node);
        return node;
    }
    
    Node(Thread thread, Node mode) {     // Used by addWaiter
        this.nextWaiter = mode;
        this.thread = thread;
    }
    
    private Node enq(final Node node) {
        for (;;) {
            Node t = tail;
            //尾节点为空,初始化一个新节点,头和尾都指向他
            if (t == null) { // Must initialize
                if (compareAndSetHead(new Node()))
                    tail = head;
            } else {
            //将node节点放入尾节点之后,一次次直到成功
                node.prev = t;
                if (compareAndSetTail(t, node)) {
                    t.next = node;
                    return t;
                }
            }
        }
    }
    
    Node() {    // Used to establish initial head or SHARED marker
    }

    2.2 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; }
           //将当前节点的前一个结点的waitStatus改为-1(循环直到成功),挂起当前节点lockSupport.park
    if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) interrupted = true; } } finally { if (failed) cancelAcquire(node); } }
  • 相关阅读:
    JavasScript 实现二分法快排注意点
    JS的面向对象二(通过构造函数的方式)
    JS的面向对象一(通过构造函数的方式)
    leetcode.977_有序数组的平方
    leetcode_38.报数
    leetcode_20.c++有效的括号
    leetcode_21.c++合并两个有序列表
    leetcode_最长公共前缀
    T2_两数相加
    T1_两数之和
  • 原文地址:https://www.cnblogs.com/scorates/p/14603427.html
Copyright © 2020-2023  润新知