Spring AI 从提示词到多模态
2026/6/5 8:40:03
/** * The synchronization state. */ private volatile int state;getState() setState() compareAndSetState()static final class Node { // 标记一个结点(对应的线程)在共享模式下等待 static final Node SHARED = new Node(); // 标记一个结点(对应的线程)在独占模式下等待 static final Node EXCLUSIVE = null; // waitStatus的值,表示该结点(对应的线程)已被取消 static final int CANCELLED = 1; // waitStatus的值,表示后继结点(对应的线程)需要被唤醒 static final int SIGNAL = -1; // waitStatus的值,表示该结点(对应的线程)在等待某一条件 static final int CONDITION = -2; /*waitStatus的值,表示有资源可用,新head结点需要继续唤醒后继结点(共享模式下,多线程并发释放资源,而head唤醒其后继结点后,需要把多出来的资源留给后面的结点;设置新的head结点时,会继续唤醒其后继结点)*/ static final int PROPAGATE = -3; // 等待状态,取值范围,-3,-2,-1,0,1 volatile int waitStatus; volatile Node prev; // 前驱结点 volatile Node next; // 后继结点 volatile Thread thread; // 结点对应的线程 Node nextWaiter; // 等待队列里下一个等待条件的结点 // 判断共享模式的方法 final boolean isShared() { return nextWaiter == SHARED; } Node(Thread thread, Node mode) { // Used by addWaiter this.nextWaiter = mode; this.thread = thread; } // 其它方法忽略,可以参考具体的源码 } // AQS里面的addWaiter私有方法 private Node addWaiter(Node mode) { // 使用了Node的这个构造函数 Node node = new Node(Thread.currentThread(), mode); }public class CLHLock { private volatile Node tail; private ThreadLocal<Node> myNode = ThreadLocal.withInitial(Node::new); private ThreadLocal<Node> myPred = new ThreadLocal<>(); public void lock() { Node node = myNode.get(); node.locked = true; // 把自己放到队尾,并取出前面的节点 Node pred = tail; myPred.set(pred); while (pred.locked) { // 自旋等待 } } public void unlock() { Node node = myNode.get(); node.locked = false; myNode.set(myPred.get()); } private static class Node { private volatile boolean locked; } }protected boolean tryAcquire(int arg) { throw new UnsupportedOperationException(); }public final void acquire(int arg) { // tryAcquire 再次尝试获取锁资源,如果尝试成功,返回true,尝试失败返回false if (!tryAcquire(arg) && // 走到这,代表获取锁资源失败,需要将当前线程封装成一个Node,追加到AQS的队列中 acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) // 线程中断 selfInterrupt(); }private Node addWaiter(Node mode) { //创建 Node 类,并且设置 thread 为当前线程,设置为排它锁 Node node = new Node(Thread.currentThread(), mode); // 获取 AQS 中队列的尾部节点 Node pred = tail; // 如果 tail == null,说明是空队列, // 不为 null,说明现在队列中有数据, if (pred != null) { // 将当前节点的 prev 指向刚才的尾部节点,那么当前节点应该设置为尾部节点 node.prev = pred; // CAS 将 tail 节点设置为当前节点 if (compareAndSetTail(pred, node)) { // 将之前尾节点的 next 设置为当前节点 pred.next = node; // 返回当前节点 return node; } } enq(node); return node; } // 自旋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; } } } }final boolean acquireQueued(final Node node, int arg) { boolean failed = true; try { // interrupted用于记录线程是否被中断过 boolean interrupted = false; for (;;) { // 自旋操作 // 获取当前节点的前驱节点 final Node p = node.predecessor(); // 如果前驱节点是head节点,并且尝试获取同步状态成功 if (p == head && tryAcquire(arg)) { // 设置当前节点为head节点 setHead(node); // 前驱节点的next引用设为null,帮助垃圾回收器回收该节点 p.next = null; // 获取同步状态成功,将failed设为false failed = false; // 返回线程是否被中断过 return interrupted; } // 如果应该让当前线程阻塞并且线程在阻塞时被中断,则将interrupted设为true if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) interrupted = true; } } finally { // 如果获取同步状态失败,取消尝试获取同步状态 if (failed) cancelAcquire(node); } }public final boolean release(int arg) { if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; } return false; } private void unparkSuccessor(Node node) { // 如果状态是负数,尝试把它设置为0 int ws = node.waitStatus; if (ws < 0) compareAndSetWaitStatus(node, ws, 0); // 得到头结点的后继结点head.next Node s = node.next; // 如果这个后继结点为空或者状态大于0 // 通过前面的定义我们知道,大于0只有一种可能,就是这个结点已被取消(只有 Node.CANCELLED(=1) 这一种状态大于0) if (s == null || s.waitStatus > 0) { s = null; // 从尾部开始倒着寻找第一个还未取消的节点(真正的后继者) for (Node t = tail; t != null && t != node; t = t.prev) if (t.waitStatus <= 0) s = t; } // 如果后继结点不为空, if (s != null) LockSupport.unpark(s.thread); }