欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

J.U.C剖析与解读2(AQS的由来)

程序员文章站 2022-03-25 21:20:27
J.U.C剖析与解读2(AQS的由来) 前言 前面已经通过实现自定义ReentrantLock与自定义ReentrantReadWriteLock,展示了JDK是如何实现独占锁与共享锁的。 那么实际JDK源码中的ReentrantLock与ReentrantReadWritreLock是如何实现的呢 ......

j.u.c剖析与解读2(aqs的由来)

前言

前面已经通过实现自定义reentrantlock与自定义reentrantreadwritelock,展示了jdk是如何实现独占锁与共享锁的。

那么实际jdk源码中的reentrantlock与reentrantreadwritrelock是如何实现的呢?我们现有的自定义代码是否可以更进一步呢?

答案是肯定的。注意看我之前两个lock的朋友,应该注意到了。自定义reentrantreadwritelock的独占锁部分,其实和自定义reentrantlock是几乎一样的。

也就是说,不同lock其实现是差不多的。那么是否可以提取公共的部分,是否可以写得更加优雅一些。

那么这篇博客,就是通过提取公共代码,引入模板方法设计模式,并利用java的一些特性,写出一个自定义的aqs。

当然,最后也会剖析源码中aqs实现与我们自定义aqs的差别所在,并解读源码aqs中一些高级应用,如aqs通过一个state实现读写锁的持有数量(居然通过一个int值的cas操作,解决了自定义读写锁持有数量的独占操作)。

如果看过源码的朋友,会发现源码中的reentrantlock会自定义一个sync,该sync会继承一个abstratqueuesynchronizer(简称aqs)。然后源码中的reentrantlock的trylock等方法,则是调用sync的对应子类(fairsync或nonfairsync,也就是是否为公平锁)来实现对应功能。并且,只有tryacquire与lock两个方法是由reentrantlock实现的,其它方法是由aqs提供的。lock是由fairsync与nonfairsync分别实现的。而tryacquire是由fairsync与nonfairsync父类的sync实现,nonfairsync的trylock直接调用父类sync的nonfairtryacquire方法。

而reentrantreadwritelock则是增加了readlock与writelock,其实现,则是调用sync的不同方法而已。

有的小伙伴,会觉得这样的关系很复杂,明明一个锁就比较复杂了,还搞得这么抽象。提取一个aqs就够抽象的了,每个锁还整了一个sync,fairsync,nonfairsync内部类,视情况,还要弄个readlock,writelock这些内部类。这样做的目的其实是为了封装代码,提高代码复用性。当然,实际源码看多了,反而会觉得这样的代码,看得挺舒服的。比较符合设计理念(想想,你接收的项目中,一个类上千行代码,完全不敢修改)。

关于读源码,简单说一下我的感受。最核心的就是坚持,最重要的是全局观,最需要的是积累。

我陆陆续续阅读源码(不只是java),也有差不多两年的经验吧。从最早的windows内核源码,到后面的前端框架源码,到今年的java源码阅读。最早的windows内核源码,那真的是无知者无畏啊,简直是一段极其痛苦的经历。那时候一天可能就二十页样子,还得看运气。但是那段时间给我带来了很多,包括什么系统内存管理,内存的用户态与内核态,以及系统上下文等积累,为我后面的提升带来了很多。而后面的前端源码的阅读,也让我开始接触源码的一些思路。最后到今年的java源码,有了去年golang一些外文博客的翻译(涉及语言设计部分)铺垫,才渐渐有了一些阅读源码的感觉(自我感觉有点上路了)。所以,最核心的是坚持。

至于全局观嘛,就是一方面很多时候源码太多,常常迷路,我们需要把握主线,以及自己的目的。如果可以有一个xmind,或者比较不错的博客等作为指引就更好了。比如这次aqs拆分,我就是从网易云的大佬james学到的。虽然之前就有了juc学习的积累,但是大佬的aqs拆分,确实令我对aqs有了更为深入的理解。另一方面就是需要把握自己应该研究的深度(在自己能力层级再深入一些即可),而不是抓着源码的每个字不放。我今年年初的时候,就想研究ioc源码,根据一位大佬的,连续啃了两三个星期。但后面陆陆续续就忘了。虽然这段经历对我依旧有着一定的积累价值(对我最近研究springapplication的run过程有着不错的价值),但是超出自己能力太多地撸源码,性价比就太低了。

最后就是积累,我非常看重积累。自从高三后,我就对积累这个词有了更深入的理解。很多时候,我们阅读一些书籍,研究一些原理,虽然后来感觉忘记了,但是积累还是在的。就像我学习编程时,就经常感受到大学时期的计算机网络,计算机原理,分布式课题等经历给我带来的积累。而现在很多人都过于看重即时价值(就是我立马学了,立马就要有效果),而我相信技术的攀登,是离不开经年累月的积累的。

如果大家对阅读源码,感兴趣的话,可以告诉我。可以考虑写一篇文章,来简单谈谈源码阅读这件事儿。

一,简易juc(版本一):

这里就是将之前实现的简易版reentrantlock与reentrantreadwritelock展现出来,就当是简单回顾一下。

1.jarryreentrantlock:

    package tech.jarry.learning.netease.locks2;
    
    import java.util.concurrent.linkedblockingqueue;
    import java.util.concurrent.timeunit;
    import java.util.concurrent.atomic.atomicinteger;
    import java.util.concurrent.atomic.atomicreference;
    import java.util.concurrent.locks.condition;
    import java.util.concurrent.locks.lock;
    import java.util.concurrent.locks.locksupport;
    
    /**
     * @description: 仿reentrantlock,实现其基本功能及特性
     * @author: jarry
     */
    public class jarryreentrantlock {
    
        private atomicinteger count = new atomicinteger(0);
        private atomicreference<thread> owner = new atomicreference<>();
        private linkedblockingqueue<thread> waiters = new linkedblockingqueue<>();
    
        public void lock() {
            int arg = 1;
            if (!trylock(arg)){
                waiters.offer(thread.currentthread());
                while (true){
                    thread head = waiters.peek();
                    if (head == thread.currentthread()){
                        if (!trylock(arg)){
                            locksupport.park();
                        } else {
                            waiters.poll();
                            return;
                        }
                    } else {
                        locksupport.park();
                    }
                }
            }
        }
    
        public void unlock() {
            int arg = 1;
            if (tryunlock(arg)){
                thread head = waiters.peek();
                if (head != null){
                    locksupport.unpark(head);
                }
            }
        }
    
        public boolean trylock(int acquires) {
            int countvalue = count.get();
            if (countvalue != 0){
                if (thread.currentthread() == owner.get()){
                    count.set(countvalue+acquires);
                    return true;
                }else{
                    return false;
                }
            }else {
                if (count.compareandset(countvalue,countvalue+acquires)){
                    owner.set(thread.currentthread());
                    return true;
                } else {
                    return false;
                }
            }
        }
    
        private boolean tryunlock(int releases) {
            if (thread.currentthread() != owner.get()){
                throw new illegalmonitorstateexception();
            } else {
                int countvalue = count.get();
                int countnextvalue = countvalue - releases;
                count.compareandset(countvalue,countnextvalue);
                if (countnextvalue == 0){
                    owner.compareandset(thread.currentthread(),null);
                    return true;
                } else {
                    return false;
                }
            }
        }
    
        public void lockinterruptibly() throws interruptedexception {
    
        }
    
        public boolean trylock(long time, timeunit unit) throws interruptedexception {
            return false;
        }
    
        public condition newcondition() {
            return null;
        }
    }

2.jarryreadwritelock:

    package tech.jarry.learning.netease.locks2;
    
    import java.util.concurrent.linkedblockingqueue;
    import java.util.concurrent.atomic.atomicinteger;
    import java.util.concurrent.atomic.atomicreference;
    import java.util.concurrent.locks.locksupport;
    
    /**
     * @description:
     * @author: jarry
     */
    public class jarryreadwritelock {
    
        volatile atomicinteger readcount = new atomicinteger(0);
        atomicinteger writecount = new atomicinteger(0);
        atomicreference<thread> owner = new atomicreference<>();
        public volatile linkedblockingqueue<waitnode> waiters = new linkedblockingqueue<>();
    
        class waitnode{
            thread thread = null;
            // 表示希望争取的锁的类型。0表示写锁(独占锁),1表示读锁(共享锁)
            int type = 0;
            int arg = 0;
    
            public waitnode(thread thread, int type, int arg) {
                this.type = type;
                this.thread = thread;
                this.arg = arg;
            }
        }
    
        /**
         * 获取独占锁(针对独占锁)
         */
        public void lock(){
            int arg = 1;
            if (!trylock(arg)){
                waitnode waitnode = new waitnode(thread.currentthread(), 0, arg);
                waiters.offer(waitnode);
    
                while (true){
                    waitnode headnote = waiters.peek();
                    if (headnote !=null && headnote.thread == thread.currentthread()){
                        if (!trylock(headnote.arg)){
                            locksupport.park();
                        } else {
                            waiters.poll();
                            return;
                        }
                    }else {
                        locksupport.park();
                    }
                }
            }
        }
    
        /**
         * 解锁(针对独占锁)
         */
        public void unlock(){
            int arg = 1;
            if (tryunlock(arg)){
                waitnode head = waiters.peek();
                if (head == null){
                    return;
                }
                locksupport.unpark(head.thread);
            }
        }
    
        /**
         * 尝试获取独占锁(针对独占锁)
         * @param acquires 用于加锁次数。一般传入waitnode.arg(本代码中就是1。为什么不用一个常量1,就不知道了?)
         * @return
         */
        public boolean trylock(int acquires){
            if (readcount.get() == 0){
                int writecountvalue = writecount.get();
                if (writecountvalue == 0){
                    if (writecount.compareandset(writecountvalue,writecountvalue+acquires)){
                        owner.set(thread.currentthread());
                        return true;
                    }
                } else {
                    if (thread.currentthread() == owner.get()){
                        writecount.set(writecountvalue+acquires);
                        return true;
                    }
                }
            }
            return false;
        }
    
        /**
         * 尝试解锁(针对独占锁)
         * @param releases 用于设定解锁次数。一般传入waitnode.arg
         * @return
         */
        public boolean tryunlock(int releases){
            if (owner.get() != thread.currentthread()){
                throw new illegalmonitorstateexception();
            }
            int writecountvalue = writecount.get();
            writecount.set(writecountvalue-releases);
            if (writecount.get() == 0){
                owner.compareandset(thread.currentthread(),null);
                return true;
            } else {
                return false;
            }
        }
    
        /**
         * 获取共享锁(针对共享锁)
         */
        public void lockshared(){
            int arg = 1;
            if (!trylockshared(arg)){
                waitnode waitnode = new waitnode(thread.currentthread(),1,arg);
                waiters.offer(waitnode);
    
                while (true){
                    waitnode head = waiters.peek();
                    if (head != null && head.thread == thread.currentthread()){
                        if (trylockshared(head.arg)){
                            waiters.poll();
    
                            waitnode newhead = waiters.peek();
                            if (newhead != null && newhead.type == 1){
                                locksupport.unpark(newhead.thread);
                            }
                            return;
                        } else {
                            locksupport.park();
                        }
                    } else {
                        locksupport.park();
                    }
                }
            }
        }
    
        /**
         * 解锁(针对共享锁)
         */
        public boolean unlockshared(){
            int arg = 1;
            if (tryunlockshared(arg)){
                waitnode head = waiters.peek();
                if (head != null){
                    locksupport.unpark(head.thread);
                }
                return true;
            }
            return false;
        }
    
        /**
         * 尝试获取共享锁(针对共享锁)
         * @param acquires
         * @return
         */
        public boolean trylockshared(int acquires){
            while (true){
                if (writecount.get() == 0 || owner.get() == thread.currentthread()){
                    int readcountvalue = readcount.get();
                    if (readcount.compareandset(readcountvalue, readcountvalue+acquires)){
                        return true;
                    }
                }
                return false;
            }
        }
    
        /**
         * 尝试解锁(针对共享锁)
         * @param releases
         * @return
         */
        public boolean tryunlockshared(int releases){
            while (true){
                int readcountvalue = readcount.get();
                int readcountnext = readcountvalue - releases;
                if (readcount.compareandset(readcountvalue,readcountnext)){
                    return readcountnext == 0;
                }
            }
        }
    
    }

二,简易juc(版本二):

很明显,上面的代码中,jarryreentrantlock的trylock等方法与jarryreadwritelock*享锁的trylock等方法是类似的(本来就是从jarryreentrantlock复制过来的嘛)。那么,这里就需要引入模板方法(详见笔记《设计模式》-模板方法)。通过一个commonmask类,来提取公共方法。

1.commonmask:

    package tech.jarry.learning.netease.locks3;
    
    import java.util.concurrent.linkedblockingqueue;
    import java.util.concurrent.atomic.atomicinteger;
    import java.util.concurrent.atomic.atomicreference;
    import java.util.concurrent.locks.locksupport;
    
    /**
     * @description:
     * @author: jarry
     */
    public class commonmask {
    
        volatile atomicinteger readcount = new atomicinteger(0);
        atomicinteger writecount = new atomicinteger(0);
        atomicreference<thread> owner = new atomicreference<>();
        public volatile linkedblockingqueue<waitnode> waiters = new linkedblockingqueue<>();
    
        class waitnode{
            thread thread = null;
            // 表示希望争取的锁的类型。0表示写锁(独占锁),1表示读锁(共享锁)
            int type = 0;
            int arg = 0;
    
            public waitnode(thread thread, int type, int arg) {
                this.type = type;
                this.thread = thread;
                this.arg = arg;
            }
        }
    
        /**
         * 获取独占锁(针对独占锁)
         */
        public void lock(){
            int arg = 1;
            if (!trylock(arg)){
                waitnode waitnode = new waitnode(thread.currentthread(), 0, arg);
                waiters.offer(waitnode);
    
                while (true){
                    waitnode headnote = waiters.peek();
                    if (headnote !=null && headnote.thread == thread.currentthread()){
                        if (!trylock(headnote.arg)){
                            locksupport.park();
                        } else {
                            waiters.poll();
                            return;
                        }
                    }else {
                        locksupport.park();
                    }
                }
            }
        }
    
        /**
         * 解锁(针对独占锁)
         */
        public void unlock(){
            int arg = 1;
            if (tryunlock(arg)){
                waitnode head = waiters.peek();
                if (head == null){
                    return;
                }
                locksupport.unpark(head.thread);
            }
        }
    
        /**
         * 尝试获取独占锁(针对独占锁)
         * @param acquires 用于加锁次数。一般传入waitnode.arg(本代码中就是1。为什么不用一个常量1,就不知道了?)
         * @return
         */
        public boolean trylock(int acquires){
            if (readcount.get() == 0){
                int writecountvalue = writecount.get();
                if (writecountvalue == 0){
                    if (writecount.compareandset(writecountvalue,writecountvalue+acquires)){
                        owner.set(thread.currentthread());
                        return true;
                    }
                } else {
                    if (thread.currentthread() == owner.get()){
                        writecount.set(writecountvalue+acquires);
                        return true;
                    }
                }
            }
            return false;
        }
    
        /**
         * 尝试解锁(针对独占锁)
         * @param releases 用于设定解锁次数。一般传入waitnode.arg
         * @return
         */
        public boolean tryunlock(int releases){
            if (owner.get() != thread.currentthread()){
                throw new illegalmonitorstateexception();
            }
            int writecountvalue = writecount.get();
            writecount.set(writecountvalue-releases);
            if (writecount.get() == 0){
                owner.compareandset(thread.currentthread(),null);
                return true;
            } else {
                return false;
            }
        }
    
        /**
         * 获取共享锁(针对共享锁)
         */
        public void lockshared(){
            int arg = 1;
            if (!trylockshared(arg)){
                waitnode waitnode = new waitnode(thread.currentthread(),1,arg);
                waiters.offer(waitnode);
    
                while (true){
                    waitnode head = waiters.peek();
                    if (head != null && head.thread == thread.currentthread()){
                        if (trylockshared(head.arg)){
                            waiters.poll();
    
                            waitnode newhead = waiters.peek();
                            if (newhead != null && newhead.type == 1){
                                locksupport.unpark(newhead.thread);
                            }
                            return;
                        } else {
                            locksupport.park();
                        }
                    } else {
                        locksupport.park();
                    }
                }
            }
        }
    
        /**
         * 解锁(针对共享锁)
         */
        public boolean unlockshared(){
            int arg = 1;
            if (tryunlockshared(arg)){
                waitnode head = waiters.peek();
                if (head != null){
                    locksupport.unpark(head.thread);
                }
                return true;
            }
            return false;
        }
    
        /**
         * 尝试获取共享锁(针对共享锁)
         * @param acquires
         * @return
         */
        public boolean trylockshared(int acquires){
            while (true){
                if (writecount.get() == 0 || owner.get() == thread.currentthread()){
                    int readcountvalue = readcount.get();
                    if (readcount.compareandset(readcountvalue, readcountvalue+acquires)){
                        return true;
                    }
                }
                return false;
            }
        }
    
        /**
         * 尝试解锁(针对共享锁)
         * @param releases
         * @return
         */
        public boolean tryunlockshared(int releases){
            while (true){
                int readcountvalue = readcount.get();
                int readcountnext = readcountvalue - releases;
                if (readcount.compareandset(readcountvalue,readcountnext)){
                    return readcountnext == 0;
                }
            }
        }
    }

2.jarryreentrantlock:

    package tech.jarry.learning.netease.locks3;
    
    import java.util.concurrent.linkedblockingqueue;
    import java.util.concurrent.timeunit;
    import java.util.concurrent.atomic.atomicinteger;
    import java.util.concurrent.atomic.atomicreference;
    import java.util.concurrent.locks.condition;
    import java.util.concurrent.locks.lock;
    import java.util.concurrent.locks.locksupport;
    
    /**
     * @description: 仿reentrantlock,实现其基本功能及特性
     * @author: jarry
     */
    public class jarryreentrantlock {
    
        private commonmask commonmask = new commonmask();
    
        public void lock() {
            commonmask.lock();
        }
    
        public void unlock() {
            commonmask.unlock();
        }
    
        public boolean trylock(int acquire) {
            return commonmask.trylock(acquire);
        }
    
        private boolean tryunlock(int release) {
            return commonmask.tryunlock(release);
        }
    }

3.jarryreadwritelock:

    package tech.jarry.learning.netease.locks3;
    
    import java.util.concurrent.linkedblockingqueue;
    import java.util.concurrent.atomic.atomicinteger;
    import java.util.concurrent.atomic.atomicreference;
    import java.util.concurrent.locks.locksupport;
    
    /**
     * @description:
     * @author: jarry
     */
    public class jarryreadwritelock {
    
        private commonmask commonmask = new commonmask();
    
        /**
         * 获取独占锁(针对独占锁)
         */
        public void lock(){
            commonmask.lock();
        }
    
        /**
         * 解锁(针对独占锁)
         */
        public void unlock(){
            commonmask.unlock();
        }
    
        /**
         * 尝试获取独占锁(针对独占锁)
         * @param acquires 用于加锁次数。一般传入waitnode.arg(本代码中就是1。为什么不用一个常量1,就不知道了?)
         * @return
         */
        public boolean trylock(int acquires){
            return commonmask.trylock(acquires);
        }
    
        /**
         * 尝试解锁(针对独占锁)
         * @param releases 用于设定解锁次数。一般传入waitnode.arg
         * @return
         */
        public boolean tryunlock(int releases){
            return commonmask.tryunlock(releases);
        }
    
        /**
         * 获取共享锁(针对共享锁)
         */
        public void lockshared(){
            commonmask.lockshared();
        }
    
        /**
         * 解锁(针对共享锁)
         */
        public boolean unlockshared(){
            return commonmask.unlockshared();
        }
    
        /**
         * 尝试获取共享锁(针对共享锁)
         * @param acquires
         * @return
         */
        public boolean trylockshared(int acquires){
            return trylockshared(acquires);
        }
    
        /**
         * 尝试解锁(针对共享锁)
         * @param releases
         * @return
         */
        public boolean tryunlockshared(int releases){
            return commonmask.tryunlockshared(releases);
        }
    
    }

到了这里,大家就可以明显看出,总体代码量的下降(这还只是两个lock)。但是问题也出来了,那就是这样将所有方法都放在父类commonmask,子类进行调用,是不是显得过于死板(说得直接点,就是这种操作,完全就是将代码往父类一抛而已)。这说明,之前代码公共提取做得并不好。

重新整理思路,jarryreentrantlock与jarryreadwritelock的共同之处到底在哪里。细想一下,发现这两个方法的lock,unlock等操作是一致的,只是实际的运行逻辑方法trylock,tryunlock,trylockshared,tryunlockshared四个方法(在框架源码中,常常用doxxx方法,表示实际运行逻辑的方法)。所以commonmask应该实现的是这四个方法之外的方法,而这四个方法交由子类,来根据具体需要来实现(commonmask中,这四个方法直接抛出对应异常)。

最后,reentrantlock是有公平锁,非公平锁之分的。而通过上面的调整,现在的jarryreentrantlock可以实现自己对应方法,来展现特性(公平锁/非公平锁的选择)了。

三,简易juc(版本三):

1.commonmask:

    package tech.jarry.learning.netease.locks4;
    
    import java.util.concurrent.linkedblockingqueue;
    import java.util.concurrent.atomic.atomicinteger;
    import java.util.concurrent.atomic.atomicreference;
    import java.util.concurrent.locks.locksupport;
    
    /**
     * @description:
     * @author: jarry
     */
    public class commonmask {
    
        volatile atomicinteger readcount = new atomicinteger(0);
        atomicinteger writecount = new atomicinteger(0);
        atomicreference<thread> owner = new atomicreference<>();
        public volatile linkedblockingqueue<waitnode> waiters = new linkedblockingqueue<>();
    
        class waitnode{
            thread thread = null;
            // 表示希望争取的锁的类型。0表示写锁(独占锁),1表示读锁(共享锁)
            int type = 0;
            int arg = 0;
    
            public waitnode(thread thread, int type, int arg) {
                this.type = type;
                this.thread = thread;
                this.arg = arg;
            }
        }
    
        /**
         * 获取独占锁(针对独占锁)
         */
        public void lock(){
            int arg = 1;
            if (!trylock(arg)){
                waitnode waitnode = new waitnode(thread.currentthread(), 0, arg);
                waiters.offer(waitnode);
    
                while (true){
                    waitnode headnote = waiters.peek();
                    if (headnote !=null && headnote.thread == thread.currentthread()){
                        if (!trylock(headnote.arg)){
                            locksupport.park();
                        } else {
                            waiters.poll();
                            return;
                        }
                    }else {
                        locksupport.park();
                    }
                }
            }
        }
    
        /**
         * 解锁(针对独占锁)
         */
        public void unlock(){
            int arg = 1;
            if (tryunlock(arg)){
                waitnode head = waiters.peek();
                if (head == null){
                    return;
                }
                locksupport.unpark(head.thread);
            }
        }
    
    
        /**
         * 获取共享锁(针对共享锁)
         */
        public void lockshared(){
            int arg = 1;
            if (!trylockshared(arg)){
                waitnode waitnode = new waitnode(thread.currentthread(),1,arg);
                waiters.offer(waitnode);
    
                while (true){
                    waitnode head = waiters.peek();
                    if (head != null && head.thread == thread.currentthread()){
                        if (trylockshared(head.arg)){
                            waiters.poll();
    
                            waitnode newhead = waiters.peek();
                            if (newhead != null && newhead.type == 1){
                                locksupport.unpark(newhead.thread);
                            }
                            return;
                        } else {
                            locksupport.park();
                        }
                    } else {
                        locksupport.park();
                    }
                }
            }
        }
    
        /**
         * 解锁(针对共享锁)
         */
        public boolean unlockshared(){
            int arg = 1;
            if (tryunlockshared(arg)){
                waitnode head = waiters.peek();
                if (head != null){
                    locksupport.unpark(head.thread);
                }
                return true;
            }
            return false;
        }
    
        /**
         * 尝试获取独占锁(针对独占锁)
         * @param acquires
         * @return
         */
        public boolean trylock(int acquires){
            throw new unsupportedoperationexception();
        }
    
        /**
         * 尝试解锁(针对独占锁)
         * @param releases 用于设定解锁次数。一般传入waitnode.arg
         * @return
         */
        public boolean tryunlock(int releases){
            throw new unsupportedoperationexception();
        }
    
        /**
         * 尝试获取共享锁(针对共享锁)
         * @param acquires
         * @return
         */
        public boolean trylockshared(int acquires){
            throw new unsupportedoperationexception();
        }
    
        /**
         * 尝试解锁(针对共享锁)
         * @param releases
         * @return
         */
        public boolean tryunlockshared(int releases){
            throw new unsupportedoperationexception();
        }
    }

2.jarryreentrantlock:

    package tech.jarry.learning.netease.locks4;
    
    /**
     * @description: 仿reentrantlock,实现其基本功能及特性
     * @author: jarry
     */
    public class jarryreentrantlock {
    
        private boolean isfair;
    
        // 默认采用非公平锁,保证效率(就是参照源码)
        public jarryreentrantlock() {
            this.isfair = false;
        }
    
        public jarryreentrantlock(boolean isfair) {
            this.isfair = isfair;
        }
    
        private commonmask commonmask = new commonmask(){
    
            @override
            public boolean trylock(int acquires){
                if (isfair){
                    return tryfairlock(acquires);
                } else {
                    return trynonfairlock(acquires);
                }
            }
    
            private boolean tryfairlock(int acquires){
                // 这里简单注释一下,如何实现公平锁,其关键在于新的线程到来时,不再直接尝试获取锁,而是直接塞入队列(队列为空,也是殊途同归的)
                // 1.判断读锁(共享锁)是否被占用
                if (readcount.get() == 0){
                    // 2.判断写锁(独占锁)是否被占用
                    int writecountvalue = writecount.get();
                    if (writecountvalue == 0){
                        // 2.1 (核心区别)如果写锁未被占用,需要先对等待队列waiters进行判断
                        waitnode head = waiters.peek();
                        if (head !=null && head.thread == thread.currentthread()){
                            if (writecount.compareandset(writecountvalue,writecountvalue+acquires)){
                                owner.set(thread.currentthread());
                                return true;
                            }   // 竞争失败就直接返回false了
                        }
                    } else {
                        // 2.2 如果写锁已经被占用了,就判断是否为当前线程持有,是否进行重入操作
                        if (owner.get() == thread.currentthread()){
                            // 如果持有独占锁的线程就是当前线程,那么不需要改变owner,也不需要cas,只需要修改writecount的值即可
                            writecount.set(writecountvalue + acquires);
                            return true;
                        }
                    }
                }
                // 以上操作失败,就返回false,表示竞争锁失败
                return false;
            }
    
            private boolean trynonfairlock(int acquires){
                if (readcount.get() == 0){
                    int writecountvalue = writecount.get();
                    if (writecountvalue == 0){
                        if (writecount.compareandset(writecountvalue,writecountvalue+acquires)){
                            owner.set(thread.currentthread());
                            return true;
                        }
                    } else {
                        if (thread.currentthread() == owner.get()){
                            writecount.set(writecountvalue+acquires);
                            return true;
                        }
                    }
                }
                return false;
            }
    
            @override
            public boolean tryunlock(int releases) {
                if (owner.get() != thread.currentthread()){
                    throw new illegalmonitorstateexception();
                }
                int writecountvalue = writecount.get();
                writecount.set(writecountvalue-releases);
                if (writecount.get() == 0){
                    owner.compareandset(thread.currentthread(),null);
                    return true;
                } else {
                    return false;
                }
            }
    
            // 其它诸如共享锁的相关操作,就不进行了。如果强行调用,只会发生unsupportedoperationexception
        };
    
        public void lock() {
            commonmask.lock();
        }
    
        public void unlock() {
            commonmask.unlock();
        }
    
        public boolean trylock(int acquire) {
            return commonmask.trylock(acquire);
        }
    
        private boolean tryunlock(int release) {
            return commonmask.tryunlock(release);
        }
    }

3.jarryreadwritelock:

    package tech.jarry.learning.netease.locks4;
    
    /**
     * @description:
     * @author: jarry
     */
    public class jarryreadwritelock {
    
        private commonmask commonmask = new commonmask(){
    
            @override
            public boolean trylock(int acquires){
                if (readcount.get() == 0){
                    int writecountvalue = writecount.get();
                    if (writecountvalue == 0){
                        if (writecount.compareandset(writecountvalue,writecountvalue+acquires)){
                            owner.set(thread.currentthread());
                            return true;
                        }
                    } else {
                        if (thread.currentthread() == owner.get()){
                            writecount.set(writecountvalue+acquires);
                            return true;
                        }
                    }
                }
                return false;
            }
    
            @override
            public boolean tryunlock(int releases) {
                if (owner.get() != thread.currentthread()){
                    throw new illegalmonitorstateexception();
                }
                int writecountvalue = writecount.get();
                writecount.set(writecountvalue-releases);
                if (writecount.get() == 0){
                    owner.compareandset(thread.currentthread(),null);
                    return true;
                } else {
                    return false;
                }
            }
    
            @override
            public boolean trylockshared(int acquires) {
                while (true){
                    if (writecount.get() == 0 || owner.get() == thread.currentthread()){
                        int readcountvalue = readcount.get();
                        if (readcount.compareandset(readcountvalue, readcountvalue+acquires)){
                            return true;
                        }
                    }
                    return false;
                }
            }
    
            @override
            public boolean tryunlockshared(int releases) {
                while (true){
                    int readcountvalue = readcount.get();
                    int readcountnext = readcountvalue - releases;
                    if (readcount.compareandset(readcountvalue,readcountnext)){
                        return readcountnext == 0;
                    }
                }
            }
        };
    
    
        /**
         * 获取独占锁(针对独占锁)
         */
        public void lock(){
            commonmask.lock();
        }
    
        /**
         * 解锁(针对独占锁)
         */
        public void unlock(){
            commonmask.unlock();
        }
    
        /**
         * 尝试获取独占锁(针对独占锁)
         * @param acquires 用于加锁次数。一般传入waitnode.arg(本代码中就是1。为什么不用一个常量1,就不知道了?)
         * @return
         */
        public boolean trylock(int acquires){
            return commonmask.trylock(acquires);
        }
    
        /**
         * 尝试解锁(针对独占锁)
         * @param releases 用于设定解锁次数。一般传入waitnode.arg
         * @return
         */
        public boolean tryunlock(int releases){
            return commonmask.tryunlock(releases);
        }
    
        /**
         * 获取共享锁(针对共享锁)
         */
        public void lockshared(){
            commonmask.lockshared();
        }
    
        /**
         * 解锁(针对共享锁)
         */
        public boolean unlockshared(){
            return commonmask.unlockshared();
        }
    
        /**
         * 尝试获取共享锁(针对共享锁)
         * @param acquires
         * @return
         */
        public boolean trylockshared(int acquires){
            return trylockshared(acquires);
        }
    
        /**
         * 尝试解锁(针对共享锁)
         * @param releases
         * @return
         */
        public boolean tryunlockshared(int releases){
            return commonmask.tryunlockshared(releases);
        }
    
    }

这样看来,顺眼不少。但是,还是存在两点问题。一方面,两个lock并没有如实际源码那样,实现lock接口与readwritelock接口。另一方面,jarryreadwritelock并没有如实际源码那样,通过获取对应lock(如readlock与writelock),再进行对应锁操作(其实,就是实现readwritelock接口)。

那么就来进行改造吧。这里直接采用james大佬的最终版commonmask-jameaqs了。 这里采用自己的aqs,因为自己的aqs有一些关键注解。

四,简易juc(版本四):

1.jarryaqs:

    package tech.jarry.learning.netease.locks6;
    
    import java.util.concurrent.linkedblockingqueue;
    import java.util.concurrent.atomic.atomicinteger;
    import java.util.concurrent.atomic.atomicreference;
    import java.util.concurrent.locks.locksupport;
    
    /**
     * @description:
     * @author: jarry
     */
    public class jarryaqs {
    
        volatile atomicinteger readcount = new atomicinteger(0);
        atomicinteger writecount = new atomicinteger(0);
        atomicreference<thread> owner = new atomicreference<>();
        public volatile linkedblockingqueue<waitnode> waiters = new linkedblockingqueue<>();
    
        class waitnode{
            thread thread = null;
            // 表示希望争取的锁的类型。0表示写锁(独占锁),1表示读锁(共享锁)
            int type = 0;
            int arg = 0;
    
            public waitnode(thread thread, int type, int arg) {
                this.type = type;
                this.thread = thread;
                this.arg = arg;
            }
        }
    
        /**
         * 获取独占锁(针对独占锁)
         */
        public void lock(){
            int arg = 1;
            if (!trylock(arg)){
                waitnode waitnode = new waitnode(thread.currentthread(), 0, arg);
                waiters.offer(waitnode);
    
                while (true){
                    waitnode headnote = waiters.peek();
                    if (headnote !=null && headnote.thread == thread.currentthread()){
                        if (!trylock(headnote.arg)){
                            locksupport.park();
                        } else {
                            waiters.poll();
                            return;
                        }
                    }else {
                        locksupport.park();
                    }
                }
            }
        }
    
        /**
         * 解锁(针对独占锁)
         */
        public void unlock(){
            int arg = 1;
            if (tryunlock(arg)){
                waitnode head = waiters.peek();
                if (head == null){
                    return;
                }
                locksupport.unpark(head.thread);
            }
        }
    
    
        /**
         * 获取共享锁(针对共享锁)
         */
        public void lockshared(){
            int arg = 1;
            if (!trylockshared(arg)){
                waitnode waitnode = new waitnode(thread.currentthread(),1,arg);
                waiters.offer(waitnode);
    
                while (true){
                    waitnode head = waiters.peek();
                    if (head != null && head.thread == thread.currentthread()){
                        if (trylockshared(head.arg)){
                            waiters.poll();
    
                            waitnode newhead = waiters.peek();
                            if (newhead != null && newhead.type == 1){
                                locksupport.unpark(newhead.thread);
                            }
                            return;
                        } else {
                            locksupport.park();
                        }
                    } else {
                        locksupport.park();
                    }
                }
            }
        }
    
        /**
         * 解锁(针对共享锁)
         */
        public boolean unlockshared(){
            int arg = 1;
            if (tryunlockshared(arg)){
                waitnode head = waiters.peek();
                if (head != null){
                    locksupport.unpark(head.thread);
                }
                return true;
            }
            return false;
        }
    
        /**
         * 尝试获取独占锁(针对独占锁)
         * @param acquires
         * @return
         */
        public boolean trylock(int acquires){
            throw new unsupportedoperationexception();
        }
    
        /**
         * 尝试解锁(针对独占锁)
         * @param releases 用于设定解锁次数。一般传入waitnode.arg
         * @return
         */
        public boolean tryunlock(int releases){
            throw new unsupportedoperationexception();
        }
    
        /**
         * 尝试获取共享锁(针对共享锁)
         * @param acquires
         * @return
         */
        public boolean trylockshared(int acquires){
            throw new unsupportedoperationexception();
        }
    
        /**
         * 尝试解锁(针对共享锁)
         * @param releases
         * @return
         */
        public boolean tryunlockshared(int releases){
            throw new unsupportedoperationexception();
        }
    }

2.jarryreentrantlock:

    
    package tech.jarry.learning.netease.locks6;
    
    import java.util.concurrent.timeunit;
    import java.util.concurrent.locks.condition;
    import java.util.concurrent.locks.lock;
    
    /**
     * @description: 仿reentrantlock,实现其基本功能及特性
     * @author: jarry
     */
    public class jarryreentrantlock implements lock {
    
        private boolean isfair;
    
        // 默认采用非公平锁,保证效率(就是参照源码)
        public jarryreentrantlock() {
            this.isfair = false;
        }
    
        public jarryreentrantlock(boolean isfair) {
            this.isfair = isfair;
        }
    
        private jarryaqs jarryaqs = new jarryaqs(){
    
            @override
            // 源码中,则是将fairsync与nonfairsync作为两个单独内布类(extend sync),来实现的。那样会更加优雅,耦合度更低,扩展性更好(而且实际源码,需要重写的部分也会更多,而不像这个自定义demo,只有一个trylock方法需要重写)
            public boolean trylock(int acquires){
                if (isfair){
                    return tryfairlock(acquires);
                } else {
                    return trynonfairlock(acquires);
                }
            }
    
            private boolean tryfairlock(int acquires){
                // 这里简单注释一下,如何实现公平锁,其关键在于新的线程到来时,不再直接尝试获取锁,而是直接塞入队列(队列为空,也是殊途同归的)
                // 1.判断读锁(共享锁)是否被占用
                if (readcount.get() == 0){
                    // 2.判断写锁(独占锁)是否被占用
                    int writecountvalue = writecount.get();
                    if (writecountvalue == 0){
                        // 2.1 (核心区别)如果写锁未被占用,需要先对等待队列waiters进行判断
                        waitnode head = waiters.peek();
                        if (head !=null && head.thread == thread.currentthread()){
                            if (writecount.compareandset(writecountvalue,writecountvalue+acquires)){
                                owner.set(thread.currentthread());
                                return true;
                            }   // 竞争失败就直接返回false了
                        }
                    } else {
                        // 2.2 如果写锁已经被占用了,就判断是否为当前线程持有,是否进行重入操作
                        if (owner.get() == thread.currentthread()){
                            // 如果持有独占锁的线程就是当前线程,那么不需要改变owner,也不需要cas,只需要修改writecount的值即可
                            writecount.set(writecountvalue + acquires);
                            return true;
                        }
                    }
                }
                // 以上操作失败,就返回false,表示竞争锁失败
                return false;
            }
    
            private boolean trynonfairlock(int acquires){
                if (readcount.get() == 0){
                    int writecountvalue = writecount.get();
                    if (writecountvalue == 0){
                        if (writecount.compareandset(writecountvalue,writecountvalue+acquires)){
                            owner.set(thread.currentthread());
                            return true;
                        }
                    } else {
                        if (thread.currentthread() == owner.get()){
                            writecount.set(writecountvalue+acquires);
                            return true;
                        }
                    }
                }
                return false;
            }
    
            @override
            /**
             *
             先通过临时变量c,判断是否接下来的操作会完全解锁。
             如果完全解锁,先释放owner,再通过setstate将count(源码中为state)修改为0。
             这样调换了一下顺序,但是避免了owner的原子性问题(毕竟别的线程是通过state来判断是否可以竞争锁,修改owner的)。
             */
            public boolean tryunlock(int releases) {
                if (owner.get() != thread.currentthread()){
                    throw new illegalmonitorstateexception();
                }
                int writecountnextvalue = writecount.get() - releases;
                boolean result = false;
                if (writecountnextvalue == 0){
                    result = true;
                    owner.set(null);
                }
                writecount.set(writecountnextvalue);
                return result;
            }
    
            // 其它诸如共享锁的相关操作,就不进行了。如果强行调用,只会发生unsupportedoperationexception
        };
    
        @override
        public void lock() {
            jarryaqs.lock();
        }
    
        @override
        public void lockinterruptibly() throws interruptedexception {
    
        }
    
        @override
        public boolean trylock() {
            return jarryaqs.trylock(1);
        }
    
        @override
        public boolean trylock(long time, timeunit unit) throws interruptedexception {
            return false;
        }
    
        @override
        public void unlock() {
            jarryaqs.unlock();
        }
    
        @override
        public condition newcondition() {
            return null;
        }
    
    }

3.jarryreadwritelock:

    
    package tech.jarry.learning.netease.locks6;
    
    import java.util.concurrent.timeunit;
    import java.util.concurrent.locks.condition;
    import java.util.concurrent.locks.lock;
    import java.util.concurrent.locks.readwritelock;
    
    /**
     * @description:
     * @author: jarry
     */
    public class jarryreadwritelock implements readwritelock {
    
        private jarryaqs jarryaqs = new jarryaqs(){
    
            @override
            // 实际源码,是通过sync类,继承aqs,再进行override的。
            public boolean trylock(int acquires){
                if (readcount.get() == 0){
                    int writecountvalue = writecount.get();
                    if (writecountvalue == 0){
                        if (writecount.compareandset(writecountvalue,writecountvalue+acquires)){
                            owner.set(thread.currentthread());
                            return true;
                        }
                    } else {
                        if (thread.currentthread() == owner.get()){
                            writecount.set(writecountvalue+acquires);
                            return true;
                        }
                    }
                }
                return false;
            }
    
            @override
            public boolean tryunlock(int releases) {
                if (owner.get() != thread.currentthread()){
                    throw new illegalmonitorstateexception();
                }
                int writecountnextvalue = writecount.get() - releases;
                boolean result = false;
                if (writecountnextvalue == 0){
                    result = true;
                    owner.set(null);
                }
                writecount.set(writecountnextvalue);
                return result;
            }
    
            @override
            public boolean trylockshared(int acquires) {
                while (true){
                    if (writecount.get() == 0 || owner.get() == thread.currentthread()){
                        int readcountvalue = readcount.get();
                        if (readcount.compareandset(readcountvalue, readcountvalue+acquires)){
                            return true;
                        }
                    }
                    return false;
                }
            }
    
            @override
            public boolean tryunlockshared(int releases) {
                while (true){
                    int readcountvalue = readcount.get();
                    int readcountnext = readcountvalue - releases;
                    if (readcount.compareandset(readcountvalue,readcountnext)){
                        return readcountnext == 0;
                    }
                }
            }
        };
    
    
        /**
         * 获取独占锁(针对独占锁)
         */
        public void lock(){
            jarryaqs.lock();
        }
    
        /**
         * 解锁(针对独占锁)
         */
        public void unlock(){
            jarryaqs.unlock();
        }
    
        /**
         * 尝试获取独占锁(针对独占锁)
         * @param acquires 用于加锁次数。一般传入waitnode.arg(本代码中就是1。为什么不用一个常量1,就不知道了?)
         * @return
         */
        public boolean trylock(int acquires){
            return jarryaqs.trylock(acquires);
        }
    
        /**
         * 尝试解锁(针对独占锁)
         * @param releases 用于设定解锁次数。一般传入waitnode.arg
         * @return
         */
        public boolean tryunlock(int releases){
            return jarryaqs.tryunlock(releases);
        }
    
        /**
         * 获取共享锁(针对共享锁)
         */
        public void lockshared(){
            jarryaqs.lockshared();
        }
    
        /**
         * 解锁(针对共享锁)
         */
        public boolean unlockshared(){
            return jarryaqs.unlockshared();
        }
    
        /**
         * 尝试获取共享锁(针对共享锁)
         * @param acquires
         * @return
         */
        public boolean trylockshared(int acquires){
            return trylockshared(acquires);
        }
    
        /**
         * 尝试解锁(针对共享锁)
         * @param releases
         * @return
         */
        public boolean tryunlockshared(int releases){
            return jarryaqs.tryunlockshared(releases);
        }
    
        @override
        public lock readlock() {
            return new lock() {
                @override
                public void lock() {
                    jarryaqs.lockshared();
                }
    
                @override
                public void lockinterruptibly() throws interruptedexception {
    
                }
    
                @override
                public boolean trylock() {
                    return jarryaqs.trylockshared(1);
                }
    
                @override
                public boolean trylock(long time, timeunit unit) throws interruptedexception {
                    return false;
                }
    
                @override
                public void unlock() {
                    jarryaqs.unlockshared();
                }
    
                @override
                public condition newcondition() {
                    return null;
                }
            };
        }
    
        @override
        public lock writelock() {
            return new lock() {
                @override
                public void lock() {
                    jarryaqs.lock();
                }
    
                @override
                public void lockinterruptibly() throws interruptedexception {
    
                }
    
                @override
                public boolean trylock() {
                    return jarryaqs.trylock(1);
                }
    
                @override
                public boolean trylock(long time, timeunit unit) throws interruptedexception {
                    return false;
                }
    
                @override
                public void unlock() {
                    jarryaqs.unlock();
                }
    
                @override
                public condition newcondition() {
                    return null;
                }
            };
        }
    }

到了这里,其实juc的核心-aqs,已经揭露出来了。通过这个,就可以把握住aqs核心运行机制。而实际的aqs,无非就是修改了存储线程的waitnodes,采用了node形成链表。并通过head与tail的应用,来提高效率。当然还有lockinterruptibly等没有提及,也有condition这样的大头没有说。这部分就留待以后有机会,再深入吧。

另外,再给出这方面的提升道路。如果希望更加深入理解aqs源码,可以一边阅读源码(思考源码实现与自己实现的区别),一边扩展自定义简易aqs。

如,我了解到aqs是通过一个state来同时实现独占锁与共享锁的持有数量。那么我就在jarryaqs中,去尝试实现,从而进一步理解它。

五,简易juc(版本x-扩展state):

1.jarryaqs:

    package tech.jarry.learning.netease.locks7;
    
    import sun.misc.unsafe;
    
    import java.lang.reflect.field;
    import java.util.concurrent.linkedblockingqueue;
    import java.util.concurrent.atomic.atomicinteger;
    import java.util.concurrent.atomic.atomicreference;
    import java.util.concurrent.locks.locksupport;
    
    /**
     * @description:
     * @author: jarry
     */
    public class jarryaqs {
    
        static final int shared_shift   = 16;
        static final int shared_unit    = (1 << shared_shift);
        static final int max_count      = (1 << shared_shift) - 1;
        static final int exclusive_mask = (1 << shared_shift) - 1;
    
        /** returns the number of shared holds represented in count  */
        static int sharedcount(int c)    { return c >>> shared_shift; }
        /** returns the number of exclusive holds represented in count  */
        static int exclusivecount(int c) { return c & exclusive_mask; }
    
        /**
         * the synchronization state.
         */
        public volatile int state;
        private static unsafe unsafe;
        private static long stateoffset;
        static{
            try {
                field field = unsafe.class.getdeclaredfield("theunsafe");
                field.setaccessible(true);
                unsafe = (unsafe) field.get(null);
    
                field fieldi = jarryaqs.class.getdeclaredfield("state");
                stateoffset = unsafe.objectfieldoffset(fieldi);
    
            } catch (nosuchfieldexception | illegalaccessexception e) {
                e.printstacktrace();
            }
        }
        protected final boolean compareandsetstate(int expect, int update) {
            // see below for intrinsics setup to support this
            return unsafe.compareandswapint(this, stateoffset, expect, update);
        }
    
    
        
        volatile atomicinteger readcount = new atomicinteger(0);
        atomicinteger writecount = new atomicinteger(0);
    
        atomicreference<thread> owner = new atomicreference<>();
        public volatile linkedblockingqueue<waitnode> waiters = new linkedblockingqueue<>();
    
        class waitnode{
            thread thread = null;
            // 表示希望争取的锁的类型。0表示写锁(独占锁),1表示读锁(共享锁)
            int type = 0;
            int arg = 0;
    
            public waitnode(thread thread, int type, int arg) {
                this.type = type;
                this.thread = thread;
                this.arg = arg;
            }
        }
    
        /**
         * 获取独占锁(针对独占锁)
         */
        public void lock(){
            int arg = 1;
            if (!trylock(arg)){
                waitnode waitnode = new waitnode(thread.currentthread(), 0, arg);
                waiters.offer(waitnode);
    
                while (true){
                    waitnode headnote = waiters.peek();
                    if (headnote !=null && headnote.thread == thread.currentthread()){
                        if (!trylock(headnote.arg)){
                            locksupport.park();
                        } else {
                            waiters.poll();
                            return;
                        }
                    }else {
                        locksupport.park();
                    }
                }
            }
        }
    
        /**
         * 解锁(针对独占锁)
         */
        public void unlock(){
            int arg = 1;
            if (tryunlock(arg)){
                waitnode head = waiters.peek();
                if (head == null){
                    return;
                }
                locksupport.unpark(head.thread);
            }
        }
    
    
        /**
         * 获取共享锁(针对共享锁)
         */
        public void lockshared(){
            int arg = 1;
            if (!trylockshared(arg)){
                waitnode waitnode = new waitnode(thread.currentthread(),1,arg);
                waiters.offer(waitnode);
    
                while (true){
                    waitnode head = waiters.peek();
                    if (head != null && head.thread == thread.currentthread()){
                        if (trylockshared(head.arg)){
                            waiters.poll();
    
                            waitnode newhead = waiters.peek();
                            if (newhead != null && newhead.type == 1){
                                locksupport.unpark(newhead.thread);
                            }
                            return;
                        } else {
                            locksupport.park();
                        }
                    } else {
                        locksupport.park();
                    }
                }
            }
        }
    
        /**
         * 解锁(针对共享锁)
         */
        public boolean unlockshared(){
            int arg = 1;
            if (tryunlockshared(arg)){
                waitnode head = waiters.peek();
                if (head != null){
                    locksupport.unpark(head.thread);
                }
                return true;
            }
            return false;
        }
    
        /**
         * 尝试获取独占锁(针对独占锁)
         * @param acquires
         * @return
         */
        public boolean trylock(int acquires){
            throw new unsupportedoperationexception();
        }
    
        /**
         * 尝试解锁(针对独占锁)
         * @param releases 用于设定解锁次数。一般传入waitnode.arg
         * @return
         */
        public boolean tryunlock(int releases){
            throw new unsupportedoperationexception();
        }
    
        /**
         * 尝试获取共享锁(针对共享锁)
         * @param acquires
         * @return
         */
        public boolean trylockshared(int acquires){
            throw new unsupportedoperationexception();
        }
    
        /**
         * 尝试解锁(针对共享锁)
         * @param releases
         * @return
         */
        public boolean tryunlockshared(int releases){
            throw new unsupportedoperationexception();
        }
    }

2.jarryreentrantlock:

    package tech.jarry.learning.netease.locks7;
    
    import java.util.concurrent.timeunit;
    import java.util.concurrent.locks.condition;
    import java.util.concurrent.locks.lock;
    
    /**
     * @description: 仿reentrantlock,实现其基本功能及特性
     * @author: jarry
     */
    public class jarryreentrantlock implements lock {
    
        private boolean isfair;
    
        // 默认采用非公平锁,保证效率(就是参照源码)
        public jarryreentrantlock() {
            this.isfair = false;
        }
    
        public jarryreentrantlock(boolean isfair) {
            this.isfair = isfair;
        }
    
        // 实际源码,是通过sync类,继承aqs,再进行override的。
        private jarryaqs jarryaqs = new jarryaqs(){
    
            @override
            // 源码中,则是将fairsync与nonfairsync作为两个单独内布类(extend sync),来实现的。那样会更加优雅,耦合度更低,扩展性更好(而且实际源码,需要重写的部分也会更多,而不像这个自定义demo,只有一个trylock方法需要重写)
            public boolean trylock(int acquires){
                if (isfair){
                    return tryfairlock(acquires);
                } else {
                    return trynonfairlock(acquires);
                }
            }
    
            private boolean tryfairlock(int acquires){
                // 这里简单注释一下,如何实现公平锁,其关键在于新的线程到来时,不再直接尝试获取锁,而是直接塞入队列(队列为空,也是殊途同归的)
                // 1.判断读锁(共享锁)是否被占用
                if (readcount.get() == 0){
                    // 2.判断写锁(独占锁)是否被占用
                    int writecountvalue = writecount.get();
                    if (writecountvalue == 0){
                        // 2.1 (核心区别)如果写锁未被占用,需要先对等待队列waiters进行判断
                        waitnode head = waiters.peek();
                        if (head !=null && head.thread == thread.currentthread()){
                            if (writecount.compareandset(writecountvalue,writecountvalue+acquires)){
                                owner.set(thread.currentthread());
                                return true;
                            }   // 竞争失败就直接返回false了
                        }
                    } else {
                        // 2.2 如果写锁已经被占用了,就判断是否为当前线程持有,是否进行重入操作
                        if (owner.get() == thread.currentthread()){
                            // 如果持有独占锁的线程就是当前线程,那么不需要改变owner,也不需要cas,只需要修改writecount的值即可
                            writecount.set(writecountvalue + acquires);
                            return true;
                        }
                    }
                }
                // 以上操作失败,就返回false,表示竞争锁失败
                return false;
            }
    
            private boolean trynonfairlock(int acquires){
                if (readcount.get() == 0){
                    int writecountvalue = writecount.get();
                    if (writecountvalue == 0){
                        if (writecount.compareandset(writecountvalue,writecountvalue+acquires)){
                            owner.set(thread.currentthread());
                            return true;
                        }
                    } else {
                        if (thread.currentthread() == owner.get()){
                            writecount.set(writecountvalue+acquires);
                            return true;
                        }
                    }
                }
                return false;
            }
    
            @override
            /**
             *
             先通过临时变量c,判断是否接下来的操作会完全解锁。
             如果完全解锁,先释放owner,再通过setstate将count(源码中为state)修改为0。
             这样调换了一下顺序,但是避免了owner的原子性问题(毕竟别的线程是通过state来判断是否可以竞争锁,修改owner的)。
             */
            public boolean tryunlock(int releases) {
                if (owner.get() != thread.currentthread()){
                    throw new illegalmonitorstateexception();
                }
                int writecountnextvalue = writecount.get() - releases;
                boolean result = false;
                if (writecountnextvalue == 0){
                    result = true;
                    owner.set(null);
                }
                writecount.set(writecountnextvalue);
                return result;
            }
    
            // 其它诸如共享锁的相关操作,就不进行了。如果强行调用,只会发生unsupportedoperationexception
        };
    
        @override
        public void lock() {
            jarryaqs.lock();
        }
    
        @override
        public void lockinterruptibly() throws interruptedexception {
    
        }
    
        @override
        public boolean trylock() {
            return jarryaqs.trylock(1);
        }
    
        @override
        public boolean trylock(long time, timeunit unit) throws interruptedexception {
            return false;
        }
    
        @override
        public void unlock() {
            jarryaqs.unlock();
        }
    
        @override
        public condition newcondition() {
            return null;
        }
    
    }

3.jarryreadwritelock:

    package tech.jarry.learning.netease.locks7;
    
    import java.util.concurrent.timeunit;
    import java.util.concurrent.locks.condition;
    import java.util.concurrent.locks.lock;
    import java.util.concurrent.locks.readwritelock;
    
    /**
     * @description:
     * @author: jarry
     */
    public class jarryreadwritelock implements readwritelock {
    
        // 实际源码,是通过sync类,继承aqs,再进行override的。
        private jarryaqs jarryaqs = new jarryaqs(){
    
            @override
            public boolean trylock(int acquires){
                int statetemp = state;
                if (sharedcount(statetemp) == 0){
                    int writecountvalue = exclusivecount(statetemp);
                    if (writecountvalue == 0){
                        if (compareandsetstate(statetemp,statetemp+acquires)){
                            owner.set(thread.currentthread());
                            return true;
                        }
                    } else {
                        if (thread.currentthread() == owner.get()){
                            compareandsetstate(statetemp,statetemp+acquires);
                            return true;
                        }
                    }
                }
                return false;
            }
    
            @override
            public boolean tryunlock(int releases) {
                int statetemp = state;
                if (owner.get() != thread.currentthread()){
                    throw new illegalmonitorstateexception();
                }
                int writecountnextvalue = exclusivecount(statetemp) - releases;
                boolean result = false;
                if (writecountnextvalue == 0){
                    result = true;
                    owner.set(null);
                }
                compareandsetstate(statetemp,statetemp - releases);
                return result;
            }
    
            @override
            public boolean trylockshared(int acquires) {
                while (true){
                    int statetemp = state;
                    if (exclusivecount(statetemp) == 0 || owner.get() == thread.currentthread()){
                        if (compareandsetstate(statetemp, statetemp+shared_unit*acquires)){
                            return true;
                        }
                    }
                    return false;
                }
            }
    
            @override
            public boolean tryunlockshared(int releases) {
                while (true){
                    int statetemp = state;
                    int readcountvalue = sharedcount(statetemp);
                    int readcountnext = readcountvalue - releases;
                    if (compareandsetstate(statetemp, statetemp-shared_unit*readcountnext)){
                        return readcountnext == 0;
                    }
                }
            }
        };
    
    
        /**
         * 获取独占锁(针对独占锁)
         */
        public void lock(){
            jarryaqs.lock();
        }
    
        /**
         * 解锁(针对独占锁)
         */
        public void unlock(){
            jarryaqs.unlock();
        }
    
        /**
         * 尝试获取独占锁(针对独占锁)
         * @param acquires 用于加锁次数。一般传入waitnode.arg(本代码中就是1。为什么不用一个常量1,就不知道了?)
         * @return
         */
        public boolean trylock(int acquires){
            return jarryaqs.trylock(acquires);
        }
    
        /**
         * 尝试解锁(针对独占锁)
         * @param releases 用于设定解锁次数。一般传入waitnode.arg
         * @return
         */
        public boolean tryunlock(int releases){
            return jarryaqs.tryunlock(releases);
        }
    
        /**
         * 获取共享锁(针对共享锁)
         */
        public void lockshared(){
            jarryaqs.lockshared();
        }
    
        /**
         * 解锁(针对共享锁)
         */
        public boolean unlockshared(){
            return jarryaqs.unlockshared();
        }
    
        /**
         * 尝试获取共享锁(针对共享锁)
         * @param acquires
         * @return
         */
        public boolean trylockshared(int acquires){
            return trylockshared(acquires);
        }
    
        /**
         * 尝试解锁(针对共享锁)
         * @param releases
         * @return
         */
        public boolean tryunlockshared(int releases){
            return jarryaqs.tryunlockshared(releases);
        }
    
        @override
        public lock readlock() {
            return new lock() {
                @override
                public void lock() {
                    jarryaqs.lockshared();
                }
    
                @override
                public void lockinterruptibly() throws interruptedexception {
    
                }
    
                @override
                public boolean trylock() {
                    return jarryaqs.trylockshared(1);
                }
    
                @override
                public boolean trylock(long time, timeunit unit) throws interruptedexception {
                    return false;
                }
    
                @override
                public void unlock() {
                    jarryaqs.unlockshared();
                }
    
                @override
                public condition newcondition() {
                    return null;
                }
            };
        }
    
        @override
        public lock writelock() {
            return new lock() {
                @override
                public void lock() {
                    jarryaqs.lock();
                }
    
                @override
                public void lockinterruptibly() throws interruptedexception {
    
                }
    
                @override
                public boolean trylock() {
                    return jarryaqs.trylock(1);
                }
    
                @override
                public boolean trylock(long time, timeunit unit) throws interruptedexception {
                    return false;
                }
    
                @override
                public void unlock() {
                    jarryaqs.unlock();
                }
    
                @override
                public condition newcondition() {
                    return null;
                }
            };
        }
    }

六,总结:

如果是从reentrantlock实现,一步步走到这里,手动撸到这里,那么你对aqs的认知,就有了非常坚实的基础。如果能够在学习过程中,对照源码学习(一边自己实现,一边了解源码是怎么解决相关问题的),那么你对aqs的理解就很不错了。即使有所欠缺,也只是aqs阅读积累方面了。