• ReentrantLock(可重入锁)


    基于AQS实现的可重入锁,包括公平和非公平两种实现方式。

    公平与非公平的差异:

    1、非公平:主动抢锁,抢锁失败,进入AQS实现的获取锁流程(排队去)

    2、公平锁:不主动抢锁,直接进入AQS的获取锁方法(排队去),这也是公平与非公平锁(主动尝试抢锁)的区别

    可重入主要体现在对同一线程访问资源时,对资源state的值叠加

    public class ReentrantLock implements Lock, java.io.Serializable {
    
        //提供所有实现机制的同步器
        private final Sync sync;
    
        /**
         * 继承至AQS的同步器基础类,子类分公平和非公平实现。用AQS的state表示获取锁资源的数量
         */
        abstract static class Sync extends AbstractQueuedSynchronizer {
            //获取锁的抽象方法,由子类具体实现
            abstract void lock();
    
            //非公平锁获取锁的方法
            final boolean nonfairTryAcquire(int acquires) {
                //获取当前线程
                final Thread current = Thread.currentThread();
                //获取AQS的state值
                int c = getState();
                //尝试获取锁
                if (c == 0) {
                    //cas继续尝试获取
                    if (compareAndSetState(0, acquires)) {
                        //获取成功,设置获取到互斥锁的当前线程
                        setExclusiveOwnerThread(current);
                        return true;
                    }
                }
                //如果没有锁资源,则判断当前锁线程是否就是自己,如果是则进入方法,这块是可重入思想的主要实现
                else if (current == getExclusiveOwnerThread()) { 
                    //注意:这里分支块为啥没有CAS呢?因为进入这个方法时,当前线程算是重入,这就证明已经是加过互斥锁的,不存在竞争问题
                    //用AQS的state记录可重入次数
                    int nextc = c + acquires;
                    if (nextc < 0) // 超出int范围,超出会变成负数
                        throw new Error("Maximum lock count exceeded");
                    setState(nextc);  //设置AQS state值
                    return true;
                }
                return false;
            }
    
            //释放锁资源的方法(不区分公平与非公平方式)
            protected final boolean tryRelease(int releases) {
                int c = getState() - releases;  //用原state减去释放的资源值
                if (Thread.currentThread() != getExclusiveOwnerThread()) 
                    //当前释放资源的线程并不是获取锁的线程,抛出异常
                    throw new IllegalMonitorStateException();
                boolean free = false;
                if (c == 0) {  //完全释放成功,其他线程可以获取锁了
                    free = true;
                    setExclusiveOwnerThread(null);
                }
                setState(c);  //更新state值
                return free;
            }
    		//判断是否获取到锁
            protected final boolean isHeldExclusively() {
                return getExclusiveOwnerThread() == Thread.currentThread();
            }
    		//创建条件对象
            final ConditionObject newCondition() {
                return new ConditionObject();
            }
    
            //拿到获取锁的线程
            final Thread getOwner() {
                return getState() == 0 ? null : getExclusiveOwnerThread();
            }
    		//获取锁资源数量(可重入次数)
            final int getHoldCount() {
                return isHeldExclusively() ? getState() : 0;
            }
    
            final boolean isLocked() {
                return getState() != 0;
            }
    
            /**
             * Reconstitutes the instance from a stream (that is, deserializes it).
             */
            private void readObject(java.io.ObjectInputStream s)
                throws java.io.IOException, ClassNotFoundException {
                s.defaultReadObject();
                setState(0); // reset to unlocked state
            }
        }
    
        //实现非公平锁的同步器
        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值,意为抢锁
                if (compareAndSetState(0, 1))  
                    //抢锁成功,设置互斥锁拥有线程为当前线程
                    setExclusiveOwnerThread(Thread.currentThread());
                else
                    acquire(1); //抢锁失败,进入AQS实现的获取锁流程
            }
    
            protected final boolean tryAcquire(int acquires) {
                //调用父类提供的非公平锁获取方法
                return nonfairTryAcquire(acquires);
            }
        }
    
        //实现公平锁的同步器
        static final class FairSync extends Sync {
            private static final long serialVersionUID = -3000897897090466540L;
    
            final void lock() {
                //不主动抢锁,直接进入AQS的获取锁方法,这也是公平与非公平锁(主动尝试抢锁)的区别
                acquire(1);
            }
    
            //获取锁的实现,给AQS调用的勾子函数的子类实现方法
            protected final boolean tryAcquire(int acquires) {
                final Thread current = Thread.currentThread();
                int c = getState();
                if (c == 0) {
                    //没有其他线程上锁,CAS抢锁
                    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;
            }
        }
    
        //默认构造函数,创建的是非公平锁同步器
        public ReentrantLock() {
            sync = new NonfairSync();
        }
    	//根据fair来创建公平和非公平锁同步器
        public ReentrantLock(boolean fair) {
            sync = fair ? new FairSync() : new NonfairSync();
        }
    	//锁操作,调用sync同步器lock方法
        public void lock() {
            sync.lock();
        }
    
        public void lockInterruptibly() throws InterruptedException {
            sync.acquireInterruptibly(1);
        }
    
        public boolean tryLock() {
            return sync.nonfairTryAcquire(1);
        }
    
        public boolean tryLock(long timeout, TimeUnit unit)
                throws InterruptedException {
            return sync.tryAcquireNanos(1, unit.toNanos(timeout));
        }
    	//释放锁
        public void unlock() {
            sync.release(1);
        }
    
        //获取AQS条件对象
        public Condition newCondition() {
            return sync.newCondition();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
  • 相关阅读:
    【MATLAB源码-第79期】基于蚯蚓优化算法(EOA)的栅格路径规划,输出做短路径图和适应度曲线。
    Python 爬虫之scrapy 库
    VEX —— Functions|Volume
    突破编程_C++_设计模式(解释器模式)
    pyhon项目中,使用pip安装第三方插件之后,明明使用pip list可以查到,但是在项目中import时仍然找不到怎么办?
    第三章 将对象映射到 XML - 使用列表或数组定义的属性
    Day 47、48 操作系统的运行机制与体系结构
    (十七)admin-boot项目之国际化支持
    如何解决 chrome 浏览器标签过多无法查看到标题的情况
    【MAPBOX基础功能】12、mapbox点击点位图层高亮指定的点位
  • 原文地址:https://blog.csdn.net/zhang527294844/article/details/133899626