【JUC并发】3. AQS不为认知的秘密!

目录

1. AQS简介

2. AQS的工作原理

2.1 AQS的基本结构

2.2 Node类

2.3 同步状态

2.4 独占模式下的同步器

2.5 共享模式下的同步器

2.6 等待队列

2.7 每个同步器的实现

3. 总结


1. AQS简介

AQS(AbstractQueuedSynchronizer)是JUC并发包中的一个核心类,它提供了一种实现同步器的框架,如ReentrantLockSemaphoreCountDownLatchCyclicBarrier等都是基于AQS实现的。

AQS的核心思想是维护一个双向链表,其中链表的每个节点都表示一个线程,线程通过竞争锁来加入到链表中,当锁被释放时,链表中的下一个线程可以获取到锁。同时,AQS还提供了Condition接口,用于实现等待/通知机制。

2. AQS的工作原理

  • AQS内部维护了一个state变量,用来表示当前共享资源的状态。当有线程请求获取锁时,如果锁没有被其他线程占用,则该线程可以直接获取到锁;否则,该线程会被加入到等待队列中,等待锁的释放。
  • 当锁被释放时,AQS会从等待队列中取出一个线程,并将锁的状态分配给该线程,使其获得锁。如果等待队列中还有其他线程,则继续从队列中取出线程,并分配锁的状态,直到队列为空或者锁的状态无法分配为止。

2.1 AQS的基本结构

public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements Serializable {
    private static final long serialVersionUID = 7373984972572414691L;

    protected AbstractQueuedSynchronizer() { }

    static final class Node {
        static final Node SHARED = new Node();
        static final Node EXCLUSIVE = null;

        static final int CANCELLED =  1;
        static final int SIGNAL    = -1;
        static final int CONDITION = -2;
        static final int PROPAGATE = -3;

        volatile int waitStatus;
        volatile Node prev;
        volatile Node next;
        volatile Thread thread;
        Node nextWaiter;

        final boolean isShared() {
            return nextWaiter == SHARED;
        }

        final Node predecessor() throws NullPointerException {
            Node p = prev;
            if (p == null)
                throw new NullPointerException();
            else
                return p;
        }

        Node() {
        }

        Node(Thread thread, Node mode) {
            this.nextWaiter = mode;
            this.thread = thread;
        }

        Node(Thread thread, int waitStatus) {
            this.waitStatus = waitStatus;
            this.thread = thread;
        }
    }

    private transient volatile Node head;

    private transient volatile Node tail;

    private volatile int state;

    protected final int getState() {
        return state;
    }

    protected final void setState(int newState) {
        state = newState;
    }

    protected final boolean compareAndSetState(int expect, int update) {
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
    }

    private transient Thread exclusiveOwnerThread;

    protected final Thread getExclusiveOwnerThread() {
        return exclusiveOwnerThread;
    }

    protected final void setExclusiveOwnerThread(Thread thread) {
        exclusiveOwnerThread = thread;
    }
}

AQS的基本结构包括三部分:

  1. Node类:表示双向链表中的节点,每个节点代表一个线程。
  2. headtail:分别表示链表的头和尾。
  3. state:表示同步状态,不同的同步器可以使用state表示不同的含义。

2.2 Node类

Node类是AQS中非常重要的一个类,它表示双向链表中的节点,每个节点代表一个线程。

static final class Node {
    static final Node SHARED = new Node();
    static final Node EXCLUSIVE = null;

    static final int CANCELLED =  1;
    static final int SIGNAL    = -1;
    static final int CONDITION = -2;
    static final int PROPAGATE = -3;

    volatile int waitStatus;
    volatile Node prev;
    volatile Node next;
    volatile Thread thread;
    Node nextWaiter;

    final boolean isShared() {
        return nextWaiter == SHARED;
    }

    final Node predecessor() throws NullPointerException {
        Node p = prev;
        if (p == null)
            throw new NullPointerException();
        else
            return p;
    }

    Node() {
    }

    Node(Thread thread, Node mode) {
        this.nextWaiter = mode;
        this.thread = thread;
    }

    Node(Thread thread, int waitStatus) {
        this.waitStatus = waitStatus;
        this.thread = thread;
    }
}

Node类的主要属性包括:

  1. waitStatus:表示当前节点的等待状态,取值可能为CANCELLEDSIGNALCONDITIONPROPAGATE等。
  2. prevnext:表示链表中的前驱和后继节点。
  3. thread:表示当前节点所代表的线程。
  4. nextWaiter:表示下一个等待节点,对于独占模式下的节点,它总是为null

Node类的主要方法包括:

  1. isShared():判断当前节点是否为共享模式。
  2. predecessor():返回当前节点的前驱节点。

2.3 同步状态

同步状态是AQS中非常重要的一个概念,不同的同步器可以使用state表示不同的含义。例如,对于ReentrantLockstate表示获取锁的次数;对于Semaphorestate表示可用的许可证数量。

private volatile int state;

protected final int getState() {
    return state;
}

protected final void setState(int newState) {
    state = newState;
}

protected final boolean compareAndSetState(int expect, int update) {
    return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

state的修改使用了原子操作,compareAndSetState()方法调用了unsafe.compareAndSwapInt()方法。

2.4 独占模式下的同步器

独占模式下的同步器,例如ReentrantLock,每次只允许一个线程获取锁。

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

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

protected int tryAcquireShared(int arg) {
    throw new UnsupportedOperationException();
}

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

protected boolean isHeldExclusively() {
    throw new UnsupportedOperationException();
}

独占模式下的同步器需要实现tryAcquire()tryRelease()isHeldExclusively()方法。

2.5 共享模式下的同步器

共享模式下的同步器,例如SemaphoreCountDownLatchCyclicBarrier,允许多个线程同时获取同一个锁。

protected int tryAcquireShared(int arg) {
    throw new UnsupportedOperationException();
}

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

共享模式下的同步器需要实现tryAcquireShared()tryReleaseShared()方法。

2.6 等待队列

等待队列是AQS中非常重要的一个概念,它是由Node节点组成的双向链表,表示当前正在等待获取锁的线程。

private transient volatile Node head;

private transient volatile Node tail;

2.7 每个同步器的实现

2.7.1 CountDownLatch

CountDownLatch是一个同步工具类,它允许一个或多个线程等待其他线程完成操作后再继续执行。

public class CountDownLatch {
    private final Sync sync;

    public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }

    public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }

    public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }

    public void countDown() {
        sync.releaseShared(1);
    }

    public long getCount() {
        return sync.getCount();
    }

    public String toString() {
        return super.toString() + "[Count = " + sync.getCount() + "]";
    }

    private static final class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 4982264981922014374L;

        Sync(int count) {
            setState(count);
        }

        int getCount() {
            return getState();
        }

        protected int tryAcquireShared(int acquires) {
            return (getState() == 0) ? 1 : -1;
        }

        protected boolean tryReleaseShared(int releases) {
            for (;;) {
                int c = getState();
                if (c == 0)
                    return false;
                int nextc = c-1;
                if (compareAndSetState(c, nextc))
                    return nextc == 0;
            }
        }
    }
}

CountDownLatch的实现使用了AQS,它继承了AbstractQueuedSynchronizer类,并实现了Sync内部类。

Sync内部类继承了AbstractQueuedSynchronizer类,并实现了tryAcquireShared()tryReleaseShared()方法。

2.7.2 CyclicBarrier

CyclicBarrier是一个同步工具类,它允许一组线程相互等待,直到所有线程都到达一个屏障点后再继续执行。

public class CyclicBarrier {
    private final Sync sync;

    public CyclicBarrier(int parties, Runnable barrierAction) {
        if (parties <= 0) throw new IllegalArgumentException("parties <= 0");
        this.sync = new Sync(parties, barrierAction);
    }

    public CyclicBarrier(int parties) {
        this(parties, null);
    }

    public int getParties() {
        return sync.getParties();
    }

    public int await() throws InterruptedException, BrokenBarrierException {
        return sync.acquireSharedInterruptibly(1);
    }

    public int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException, TimeoutException {
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }

    public boolean isBroken() {
        return sync.isBroken();
    }

    public void reset() {
        sync.reset();
    }

    private static class Generation {
        boolean broken = false;
    }

    private static final class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 7684823728946441214L;

        private final int parties;
        private final Runnable barrierAction;
        private Generation generation = new Generation();

        Sync(int parties, Runnable barrierAction) {
            if (parties <= 0) throw new IllegalArgumentException("parties <= 0");
            this.parties = parties;
            this.barrierAction = barrierAction;
            setState(parties);
        }

        int getParties() {
            return parties;
        }

        boolean isBroken() {
            return generation.broken;
        }

        void reset() {
            setState(parties);
            generation = new Generation();
        }

        protected int tryAcquireShared(int acquires) {
            return doAcquireShared(acquires);
        }

        protected int tryReleaseShared(int releases) {
            if (tryReleaseSharedImpl(releases)) {
                return 1;
            } else {
                return -1;
            }
        }

        private boolean tryReleaseSharedImpl(int releases) {
            for (;;) {
                int c = getState();
                if (c == 0)
                    return false;
                int nextc = c-1;
                if (compareAndSetState(c, nextc)) {
                    if (nextc == 0) {
                        return true;
                    } else {
                        return false;
                    }
                }
            }
        }

        private int doAcquireShared(int acquires) {
            final Node current = addWaiter(Node.SHARED);
            boolean failed = true;
            int remaining = -1;
            try {
                boolean interrupted = false;
                for (;;) {
                    final Node p = current.predecessor();
                    if (p == head) {
                        int r = tryAcquireShared(acquires);
                        if (r >= 0) {
                            setHeadAndPropagate(current, r);
                            p.next = null;
                            if (interrupted) {
                                selfInterrupt();
                            }
                            failed = false;
                            return r;
                        }
                    }
                    if (shouldParkAfterFailedAcquire(p, current) && parkAndCheckInterrupt()) {
                        interrupted = true;
                    }
                }
            } finally {
                if (failed) {
                    cancelAcquire(current);
                }
            }
        }

        private void setHeadAndPropagate(Node node, int propagate) {
            Node h = head;
            setHead(node);
            if (propagate > 0 || h == null || h.waitStatus < 0 ||
                (h = head) == null || h.waitStatus < 0) {
                Node s = node.next;
                if (s == null || s.isShared()) {
                    doReleaseShared();
                }
            }
        }

        private void doReleaseShared() {
            for (;;) {
                Node h = head;
                if (h != null && h != tail) {
                    int ws = h.waitStatus;
                    if (ws == Node.SIGNAL) {
                        if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0)) {
                            continue;
                        }
                        unparkSuccessor(h);
                    } else if (ws == 0 &&
                               !compareAndSetWaitStatus(h, 0, Node.PROPAGATE)) {
                        continue;
                    }
                }
                if (h == head) {
                    break;
                }
            }
        }

        private void cancelAcquire(Node node) {
            if (node == null) {
                return;
            }
            node.thread = null;
            Node pred = node.prev;
            while (pred.waitStatus > 0) {
                node.prev = pred = pred.prev;
            }
            Node predNext = pred.next;
            node.waitStatus = Node.CANCELLED;
            if (node == tail && compareAndSetTail(node, pred)) {
                compareAndSetNext(pred, predNext, null);
            } else {
                int ws;
                if (pred != head &&
                    ((ws = pred.waitStatus) == Node.SIGNAL ||
                     (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
                    pred.thread != null) {
                    Node next = node.next;
                    if (next != null && next.waitStatus <= 0) {
                        compareAndSetNext(pred, predNext, next);
                    }
                } else {
                    unparkSuccessor(node);
                }
            }
        }
    }
}

CyclicBarrier的实现也使用了AQS,它继承了AbstractQueuedSynchronizer类,并实现了Sync内部类。

Sync内部类继承了AbstractQueuedSynchronizer类,并实现了tryAcquireShared()tryReleaseShared()方法。

3. 总结

AQS是JUC并发包中的一个核心类,它提供了一种实现同步器的框架,如ReentrantLockSemaphoreCountDownLatchCyclicBarrier等都是基于AQS实现的。

AQS的核心思想是维护一个双向链表,其中链表的每个节点都表示一个线程,线程通过竞争锁来加入到链表中,当锁被释放时,链表中的下一个线程可以获取到锁。同时,AQS还提供了Condition接口,用于实现等待/通知机制。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码上团建

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值