zoukankan      html  css  js  c++  java
  • Java中关于AbstractQueuedSynchronizer的入门(一)

    备注:博文仅仅是学习过程中的零散记录,后期整理。

     AbstractQueuedSynchronizer的简单介绍可以网上搜索,简单了解字段作用。

    示例代码,分析获取锁的过程:

    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class AQS {
        public static void main(String[] args) {
    
            Lock lock = new ReentrantLock();
    
            lock.lock();
    
            // do something
    
            lock.unlock();
    
        }
    
    }

    调用lock方法,然后间接调用:

        /**
         * 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() {
                if (compareAndSetState(0, 1))//更新state的状态值,state是用来记录获取锁的情况。state=0的话则锁没有人获取,当大于0时候表示锁被获取。重入次数。
                    setExclusiveOwnerThread(Thread.currentThread()); //AQS的exclusiveOwnerThread成员,记录当前获取锁的线程
                else
                    acquire(1);
            }
    
            protected final boolean tryAcquire(int acquires) {
                return nonfairTryAcquire(acquires);
            }
        }

    调用如上代码的lock方法,其中的compareAndSetState调用底层操作系统的CAS方法,是一个原子操作。到此就完成了获取锁。

    接下来看看重入锁申请过程,java.util.concurrent.locks.ReentrantLock.Sync.nonfairTryAcquire(int):

            /**
             * 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(); //当获取重入锁时候,判断当前线程和之前申请锁的线程是否是一个?如果不是一个的话则直接返回false
                int c = getState();
                if (c == 0) { //第一次获取锁时,state为0
                    if (compareAndSetState(0, acquires)) {
                        setExclusiveOwnerThread(current);
                        return true;
                    }
                }
          //如果不是第一次的话,则重入锁
                else if (current == getExclusiveOwnerThread()) {
                    int nextc = c + acquires; //acquires参数每一次获取锁时候,参数acquires都为1,代表依次获取锁。nextc是当前一共获取锁的次数
                    if (nextc < 0) // overflow ,重入次数过多,导致大于Int最大值溢出,抛异常
                        throw new Error("Maximum lock count exceeded");
                    setState(nextc);//更新state状态值
                    return true; //获取锁成功
                }
                return false;
            }

    接下来看看释放锁的过程,java.util.concurrent.locks.ReentrantLock.Sync.tryRelease(int):

          //unlock最终调用这个方法释放锁
            protected final boolean tryRelease(int releases) {
                int c = getState() - releases; //判断state的值,释放锁进行一次减1操作
                if (Thread.currentThread() != getExclusiveOwnerThread())//判断释放锁的线程和当初获取锁的线程是否是一个线程,不是的话则抛异常
                    throw new IllegalMonitorStateException();
                boolean free = false;
                if (c == 0) {//如果锁已经彻底释放,则将获取锁的线程设置为null
                    free = true;
                    setExclusiveOwnerThread(null);
                }
                setState(c);//更新state的状态
                return free;
            }

    重入锁的释放同上。

  • 相关阅读:
    css边框以及其他常用样式
    jemeter学习-badboy录制与代理服务器录制
    linux基础命令学习
    cookie与session
    网址保存
    安全性测试要点转摘
    Charles弱网测试转载
    java 中文乱码以及转码
    spring学习总结——高级装配学习四(运行时:值注入、spring表达式)
    spring学习总结——高级装配学习三(Bean的作用域)
  • 原文地址:https://www.cnblogs.com/leodaxin/p/7698997.html
Copyright © 2011-2022 走看看