美文网首页
AbstractQueuedSynchronizer源码分析

AbstractQueuedSynchronizer源码分析

作者: small瓜瓜 | 来源:发表于2019-07-10 10:40 被阅读0次

    AbstractQueuedSynchronizer是并发的基础组件,简称AQS,今天就对其部分源码一探究竟吧
    推荐参考博客
    AbstractQueuedSynchronizer的介绍和原理分析

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

    上面的方法首先就是让当前线程获取锁,获取到了直接退出该方法,如果没有获取到则调用acquireQueued(addWaiter(Node.EXCLUSIVE), arg)方法,将其加入到同步队列中去。

    protected boolean tryAcquire(int arg) {
            throw new UnsupportedOperationException();
        }
    

    这个方法虽然没有设置为抽象的方法但是却不能直接使用,需要子类重写该方法。作者之所以不将其定义为抽象方法,我想主要是因为这个类的功能很多,可以使用该类写出独占或是共享式的锁,二者两种锁,并不需要重写这个类中所有的类似上面的方法,如果是抽象的方法,用不到的方法也要进行重写,这是相当不必要的。
    tryAcquire独占式简单实现:

        public boolean tryAcquire(int acquires) {
            - 只有一个线程能更改该state属性,这就对应着只有一个线程可以获取锁。
    更改state属性值(获取锁)失败的线程要进入同步队列中,这就对应着没有获取锁的线
    程会进入堵塞队列中,等待获取锁的线程释放锁。
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }
    

    通过简单对AQS的状态属性进行更改,实现获取锁。
    其实这里很多人可能无法理解,为什么这样就是获取了锁,java中的synchronized同步锁其实就是通过对象头中的信息判断的,且jvm保证了只要一个线程可以获取锁,这里要实现锁,就是通过一个volatile成员属性,然后CAS保证原子性,对应内存语义就是锁的概念。

    private Node enq(final Node node) {
            for (;;) {
                Node t = tail;
                if (t == null) { // Must initialize
                    if (compareAndSetHead(new Node()))
                        tail = head;
                } else {
                    node.prev = t;
                    if (compareAndSetTail(t, node)) {
                        t.next = node;
                        return t;
                    }
                }
            }
        }
    
        private Node addWaiter(Node mode) {
            - 将当前线程构造成一个节点,加入到同步队列中
            Node node = new Node(Thread.currentThread(), mode);
            Node pred = tail;
            if (pred != null) {
                node.prev = pred;
                if (compareAndSetTail(pred, node)) {
                    pred.next = node;
                    return node;
                }
            }
            enq(node);
            return node;
        }
    

    对应获取锁(更改state值)失败的线程,将会执行上面的方法进入同步队列中

    未完待续...写的太菜了,哈哈

    相关文章

      网友评论

          本文标题:AbstractQueuedSynchronizer源码分析

          本文链接:https://www.haomeiwen.com/subject/kvsfkctx.html