zoukankan      html  css  js  c++  java
  • ReentrantLock源码解读

    在看此文章前,先要了解一下上一篇文章AbstractQueuedSynchronizer(AQS)。

    ReentrantLock

    ReentrantLock锁的实现分为两种(公平锁、非公平锁),默认是非公平锁。

    ReentrantLock lock = new ReentrantLock();
    

    Sync(公平锁和非公平锁都继承此抽象类)

    nonfairTryAcquire(尝试获取锁)

    
        /**
         * @param acquires state的增加值
         */
        final boolean nonfairTryAcquire(int acquires) {
            // 获取当前线程
            final Thread current = Thread.currentThread();
            // 获取state,0为未被线程持有,大于0为已被线程持有
            int c = getState();
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {
                    // 设置持有的线程为当前线程
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            // 【可重入】如果当前线程已经持有
            else if (current == getExclusiveOwnerThread()) {
                // 当前的state + acquires,在NonfairSync中,即当前state+1
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                // 为什么这里用setState,而不是compareAndSetState,因为当前线程已经持有,setState不会造成其他冲突
                setState(nextc);
                return true;
            }
            return false;
        }
    

    tryRelease(尝试释放锁)

            /**
             * @param releases state的增加值
             */
            protected final boolean tryRelease(int releases) {
                int c = getState() - releases;
                // 判断当前线程是否为持有锁的线程,【解铃还须系铃人】
                if (Thread.currentThread() != getExclusiveOwnerThread())
                    throw new IllegalMonitorStateException();
                // 释放标识
                boolean free = false;
                // 当state为0的时候,才表明已经没有线程持有
                if (c == 0) {
    
                    // 标识可以释放
                    free = true;
                    setExclusiveOwnerThread(null);
                }
                // 设置state
                setState(c);
                return free;
            }
    

    NonfairSync(非公平锁)

    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;
    
        final void lock() {
            // 如果状态为0(没有线程占用),则设置为1,此方法在AbstractQueuedSynchronizer中
            if (compareAndSetState(0, 1))
                // 设置当前持有的线程,此方法在AbstractOwnableSynchronizer中
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }
    
        // 试图获取锁
        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }
    

    FairSync(公平锁)

    unlock

        public void unlock() {
            sync.release(1);
        }
    
  • 相关阅读:
    CentOS7.6下 MariaDB的MHA 集群搭建(一)
    Mariadb10.4 集群压力测试(一)
    Galera 核心参数详解(一)
    Mariadb10.4+ ERROR 1118 (42000): Row size too large (> 8126). Changing some columns to TEXT or BLOB may help. In current row format, BLOB prefix of 0 bytes is stored inline.
    手动打造一个弹窗程序
    IAT HOOK
    进制的本质
    基于数组越界的缓冲区溢出
    函数调用堆栈图-c语言
    算法之二分查找(上)-c语言实现
  • 原文地址:https://www.cnblogs.com/jarjune/p/11011302.html
Copyright © 2011-2022 走看看