java 并发工具包,出自Doug Lea , 提供了jdk 自带的一些并发工具类,例如:Collections.synXXX(), CurrentHashMap。
AbstractQueuedSynchronizer (抽象队列同步器),实现了对INT 共享资源并发的 获取、等待、唤醒;
这个机制是由CLH 队列锁🔐来实现的;即将暂时获取不到锁的线程加入到队列中;
这个AQS实现原理图:

比sync 灵活,可以自己控制加🔐、解🔐;
AQ对资源的共享方式
1)独占
只有一个线程能执行;
2)共享
多个线程可以同时执行,入CountDownLatch、ReadWriteLock;
注:一般独占、共享实现时仅实现一种即可;
公平锁和非公平锁实现
非公平锁 上来就CAS抢占🔐;
公平锁 会严格按照队列方式进行,🔐被占用就排队;
线程加入等待队列时机
当调用tryAccqure() 方法 获取锁失败以后,会调用addWaiter 将当前线程封装成Node;
入参 mode 表示当前节点的状态,传递的参数是 Node.EXCLUSIVE,表示独占状
态。意味着重入锁用到了 AQS 的独占锁功能
- 将当前线程封装成 Node
- 当前链表中的 tail 节点是否为空,如果不为空,则通过 cas 操作把当前线程的
node 添加到 AQS 队列 - 如果为空或者 cas 失败,调用 enq 将节点添加到 AQS 队列
addWaiter
private Node addWaiter(Node mode) {Node node = new Node(Thread.currentThread(), mode); //把当前线程封装为 NodeNode pred = tail; //tail 是 AQS 中表示同比队列队尾的属性,默认是 nullif (pred != null) { //tail 不为空的情况下,说明队列中存在节点node.prev = pred; //把当前线程的 Node 的 prev 指向 tailif (compareAndSetTail(pred, node)) { //通过 cas 把 node加入到 AQS 队列,也就是设置为 tailpred.next = node; //设置成功以后,把原 tail 节点的 next指向当前 nodereturn node;}}enq(node); //tail=null,把 node 添加到同步队列return node;}
enq: 通过自旋的方式将当前节点加入到队列中
private Node enq(final Node node) {for (;;) {Node t = tail;if (t == null) { // Must initializeif (compareAndSetHead(new Node()))tail = head;} else {node.prev = t;if (compareAndSetTail(t, node)) {t.next = node;return t;}}}}
