坐下笔记而已
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
public abstract class AbstractOwnableSynchronizer
implements java.io.Serializable {
private static final long serialVersionUID = 3737899427754241961L;
protected AbstractOwnableSynchronizer() { }
/**
* 同步占用线程.
*/
private transient Thread exclusiveOwnerThread;
/**
* 设置当前拥有独占访问的线程。null参数表示没有线程拥有访问权。该方法不会强制执行任何同步或不稳定的字段访问。
*/
protected final void setExclusiveOwnerThread(Thread t) {
exclusiveOwnerThread = t;
}
/**
* 返回由setExclusiveOwnerThread所设置的线程,如果没有设置,则返回null。该方法不会强制执行任何同步或volatile字段访问。
*/
protected final Thread getExclusiveOwnerThread() {
return exclusiveOwnerThread;
}
}
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; //当前节点的后继节点要运行,也就是unpark
static final int CONDITION = -2; //当前节点在condition队列中等待
static final int PROPAGATE = -3; '//后继的acquireShared能够得以执行,读写锁和信号量使用'
volatile int waitStatus; //节点状态
volatile Node prev; //前驱节点
volatile Node next; //后继节点
volatile Thread thread; //节点对应的线程
Node nextWaiter; //下一个等待者
}
'waitStatus':节点状态
'SIGNAL': The successor of this node is (or will soon be) blocked (via park), so the current node must unpark its successor when it releases or cancels. To avoid races, acquire methods must first indicate they need a signal, then retry the atomic acquire, and then, on failure, block.
'SIGNAL':该节点的后续版本(或将很快)被阻塞(通过park),因此当前节点在释放或取消时必须取消其后续版本。为了避免竞争,获取方法必须首先表明它们需要一个信号,然后重试原子获取,然后,在失败时,阻塞
'CANCELLED': This node is cancelled due to timeout or interrupt. Nodes never leave this state. In particular, a thread with cancelled node never again blocks.
'CANCELLED':由于超时或中断,该节点被取消。节点永远不会离开这个状态。特别地,一个被取消节点的线程再也不会阻塞
'CONDITION': This node is currently on a condition queue. It will not be used as a sync queue node until transferred, at which time the status will be set to 0. (Use of this value here has nothing to do with the other uses of the field, but simplifies mechanics.)
'CONDITION': 该节点当前处于一个条件队列中。在传输之前,它不会被用作同步队列节点,在此期间,状态将被设置为0。(这个值的使用与该字段的其他用途没有任何关系,但简化了力学。)
'PROPAGATE': A releaseShared should be propagated to other nodes. This is set (for head node only) in doReleaseShared to ensure propagation continues, even if other operations have since intervened.
'PROPAGATE' :应该将一个释放的节点传播到其他节点。这是在doReleaseShared中设置的(仅用于头部节点),以确保传播继续,即使其他操作已经进行了干预
0: None of the above The values are arranged numerically to simplify use.
'0' :以上这些值都没有按数字进行排列,以简化使用
Non-negative values mean that a node doesn't need to signal. So, most code doesn't need to check for particular values, just for sign.
非负的值意味着节点不需要发出信号。因此,大多数代码不需要检查特定的值,只是为了符号。
The field is initialized to 0 for normal sync nodes, and CONDITION for condition nodes. It is modified using CAS (or when possible, unconditional volatile writes).
该字段被初始化为0,用于正常的同步节点,以及条件节点的条件。它使用CAS进行修改(或者在可能的情况下,无条件的volatile写操作)
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// 快速尝试在尾部添加
Node pred = tail;
if (pred != null) {
node.prev = pred;
// CAS操作tail
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
// 第一次传入线程 初始化
enq(node);
return node;
}
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;
}
}
}
进入sync队列之后,接下来就是要进行锁的获取,或者说是访问控制了,只有一个线程能够在同一时刻继续的运行,而其他的进入等待状态。
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
// 需要获取当前节点的前驱节点,而头结点所对应的含义是当前站有锁且正在运行
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
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;
}
释放时,仅仅需要将资源还回去,然后通知一下后继节点并将其唤醒。
参考:https://blog.csdn.net/blogs_broadcast/article/details/80723021