引言
AQS(AbstractQueuedSynchronizer)是Java并发工具的基础,采用乐观锁,通过CAS与自旋轻量级的获取锁。
下面简单分析一下他的核心实现:
###核心属性
锁相关属性:
1 2 3 4 5 6 7 8 9 10
|
private volatile int state;
private transient Thread exclusiveOwnerThread;
|
同步队列相关属性:
1 2 3 4 5 6 7 8 9
|
private transient volatile Node head;
private transient volatile Node tail;
|
Node节点中重要属性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
volatile Thread thread;
volatile Node prev; volatile Node next;
volatile int waitStatus; static final int CANCELLED = 1; static final int SIGNAL = -1; static final int CONDITION = -2; static final int PROPAGATE = -3;
Node nextWaiter;
|
状态
AQS中的状态,代表锁是否被获取,如果为0,则没有被任何线程获取,如果是独占锁的话,值为1,如果是共享锁,则值为持有锁的线程的数量。
当讨论独占锁时,除了获取锁之外,还要记录一下获取到锁的线程,所以有了类AbstractOwnableSynchronizer中的exclusiveOwnerThread属性。
队列
AQS中的队列是双向链表,依赖于Node节点中的prev和next属性,队列中存储了等待获取锁的集合。队列中有head和tail节点,头节点不存储等待锁线程。
如图:
CAS
以前也好好看过CAS操作,主要依赖于Unsafe类中的各种方法,保证只有一个线程能修改值,如果失败则通过for循环不断重试,直到修改成功,入等待节点入队列的操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
private Node enq(final Node node) { for (;;) { Node t = tail; if (t == null) { if (compareAndSetHead(new Node())) tail = head; } else { node.prev = t; if (compareAndSetTail(t, node)) { t.next = node; return t; } } } }
|
参考:
https://segmentfault.com/a/1190000016058789