实现分析public final void acquire(int arg)该方法以排他的方式获取锁,对中断不敏感,完成synchronized语义。
1 public final void acquire(int arg) {2 if (!tryAcquire(arg) &&3 acquireQueued(addWaiter(Node.EXCLUSIVE), arg))4 selfInterrupt();5 }
上述逻辑主要包括:
1. 尝试获取(调用tryAcquire更改状态,需要保证原子性);
在tryAcquire方法中使用了同步器提供的对state操作的方法,利用compareAndSet保证只有一个线程能够对状态进行成功修改,而没有成功修改的线程将进入sync队列排队。
2. 如果获取不到,将当前线程构造成节点Node并加入sync队列;
进入队列的每个线程都是一个节点Node,从而形成了一个双向队列,类似CLH队列,这样做的目的是线程间的通信会被限制在较小规模(也就是两个节点左右)。
3. 再次尝试获取,如果没有获取到那么将当前线程从线程调度器上摘下,进入等待状态。
使用LockSupport将当前线程unpark,关于LockSupport后续会详细介绍。
[url=][/url]
01 private Node addWaiter(Node mode) {02 Node node = new Node(Thread.currentThread(), mode);03 // 快速尝试在尾部添加04 Node pred = tail;05 if (pred != null) {06 node.prev = pred;07 if (compareAndSetTail(pred, node)) {08 pred.next = node;09 return node;10 }11 }12 enq(node);13 return node;14 }15 16 private Node enq(final Node node) {17 for (;;) {18 Node t = tail;19 if (t == null) { // Must initialize20 if (compareAndSetHead(new Node()))21 tail = head;22 } else {23 node.prev = t;24 if (compareAndSetTail(t, node)) {25 t.next = node;26 return t;27 }28 }29 }[url=][/url]