[关闭]
@huangyichun 2017-08-30T16:07:54.000000Z 字数 8218 阅读 844

AbstractQueuedSynchronizer队列同步器

多线程


更改同步状态state

  1. //同步器状态
  2. private volatile int state;
  3. //设置当前同步状态
  4. protected final void setState(int newState) {
  5. state = newState;
  6. }
  7. //采用CAS算法更新state状态
  8. protected final boolean compareAndSetState(int expect, int update) {
  9. // See below for intrinsics setup to support this
  10. return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
  11. }

同步队列FIFO双向队列

  1. static final class Node {
  2. //标记节点的等待模式为共享型模式
  3. static final Node SHARED = new Node();
  4. //标记节点的等待模式为独占型模式
  5. static final Node EXCLUSIVE = null;
  6. /** waitStatus value to indicate thread has cancelled */
  7. static final int CANCELLED = 1;
  8. /** waitStatus value to indicate successor's thread needs unparking */
  9. static final int SIGNAL = -1;
  10. /** waitStatus value to indicate thread is waiting on condition */
  11. static final int CONDITION = -2;
  12. /**
  13. * waitStatus value to indicate the next acquireShared should
  14. * unconditionally propagate
  15. */
  16. static final int PROPAGATE = -3;
  17. /**
  18. * Status field, taking on only the values:
  19. * SIGNAL: The successor of this node is (or will soon be)
  20. * blocked (via park), so the current node must
  21. * unpark its successor when it releases or
  22. * cancels. To avoid races, acquire methods must
  23. * first indicate they need a signal,
  24. * then retry the atomic acquire, and then,
  25. * on failure, block.
  26. * CANCELLED: This node is cancelled due to timeout or interrupt.
  27. * Nodes never leave this state. In particular,
  28. * a thread with cancelled node never again blocks.
  29. * CONDITION: This node is currently on a condition queue.
  30. * It will not be used as a sync queue node
  31. * until transferred, at which time the status
  32. * will be set to 0. (Use of this value here has
  33. * nothing to do with the other uses of the
  34. * field, but simplifies mechanics.)
  35. * PROPAGATE: A releaseShared should be propagated to other
  36. * nodes. This is set (for head node only) in
  37. * doReleaseShared to ensure propagation
  38. * continues, even if other operations have
  39. * since intervened.
  40. * 0: None of the above
  41. *
  42. * The values are arranged numerically to simplify use.
  43. * Non-negative values mean that a node doesn't need to
  44. * signal. So, most code doesn't need to check for particular
  45. * values, just for sign.
  46. *
  47. * The field is initialized to 0 for normal sync nodes, and
  48. * CONDITION for condition nodes. It is modified using CAS
  49. * (or when possible, unconditional volatile writes).
  50. */
  51. volatile int waitStatus;
  52. /**
  53. * Link to predecessor node that current node/thread relies on
  54. * for checking waitStatus. Assigned during enqueuing, and nulled
  55. * out (for sake of GC) only upon dequeuing. Also, upon
  56. * cancellation of a predecessor, we short-circuit while
  57. * finding a non-cancelled one, which will always exist
  58. * because the head node is never cancelled: A node becomes
  59. * head only as a result of successful acquire. A
  60. * cancelled thread never succeeds in acquiring, and a thread only
  61. * cancels itself, not any other node.
  62. */
  63. volatile Node prev;
  64. /**
  65. * Link to the successor node that the current node/thread
  66. * unparks upon release. Assigned during enqueuing, adjusted
  67. * when bypassing cancelled predecessors, and nulled out (for
  68. * sake of GC) when dequeued. The enq operation does not
  69. * assign next field of a predecessor until after attachment,
  70. * so seeing a null next field does not necessarily mean that
  71. * node is at end of queue. However, if a next field appears
  72. * to be null, we can scan prev's from the tail to
  73. * double-check. The next field of cancelled nodes is set to
  74. * point to the node itself instead of null, to make life
  75. * easier for isOnSyncQueue.
  76. */
  77. volatile Node next;
  78. /**
  79. * 获取同步状态的线程
  80. */
  81. volatile Thread thread;
  82. /**
  83. *等待队列中的后继节点。如果当前节点是共享的,那么这个字段将是一个SHARED常量
  84. *也就是说节点类型和等待队列中的后继节点共用一个字段
  85. */
  86. Node nextWaiter;
  87. /**
  88. * Returns true if node is waiting in shared mode.
  89. */
  90. final boolean isShared() {
  91. return nextWaiter == SHARED;
  92. }
  93. /**
  94. * Returns previous node, or throws NullPointerException if null.
  95. * Use when predecessor cannot be null. The null check could
  96. * be elided, but is present to help the VM.
  97. *
  98. * @return the predecessor of this node
  99. */
  100. final Node predecessor() throws NullPointerException {
  101. Node p = prev;
  102. if (p == null)
  103. throw new NullPointerException();
  104. else
  105. return p;
  106. }
  107. Node() { // Used to establish initial head or SHARED marker
  108. }
  109. Node(Thread thread, Node mode) { // Used by addWaiter
  110. this.nextWaiter = mode;
  111. this.thread = thread;
  112. }
  113. Node(Thread thread, int waitStatus) { // Used by Condition
  114. this.waitStatus = waitStatus;
  115. this.thread = thread;
  116. }
  117. }
  1. private void setHead(Node node) {
  2. head = node;
  3. node.thread = null;
  4. node.prev = null;
  5. }

独占式同步状态的获取与释放

  1. public final void acquire(int arg) {
  2. if (!tryAcquire(arg) &&
  3. acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
  4. selfInterrupt();
  5. }
  6. //保证线程安全的获取同步状态,该方法需要重写
  7. protected boolean tryAcquire(int arg) {
  8. throw new UnsupportedOperationException();
  9. }
  10. //添加同步节点
  11. private Node addWaiter(Node mode) {
  12. Node node = new Node(Thread.currentThread(), mode);//构造同步节点
  13. // Try the fast path of enq; backup to full enq on failure
  14. Node pred = tail;
  15. if (pred != null) {//如果队列不为空
  16. node.prev = pred;
  17. if (compareAndSetTail(pred, node)) {//在尾部添加节点
  18. pred.next = node;
  19. return node; //返回节点
  20. }
  21. }
  22. enq(node); //队列为空
  23. return node;
  24. }
  25. private Node enq(final Node node) {
  26. for (;;) {//无限循环
  27. Node t = tail;
  28. if (t == null) { // Must initialize
  29. if (compareAndSetHead(new Node()))//添加一个空的节点,作为头节点
  30. tail = head;
  31. } else {
  32. node.prev = t;
  33. if (compareAndSetTail(t, node)) {//将节点插入到末尾,CAS算法保障
  34. t.next = node;
  35. return t;
  36. }
  37. }
  38. }
  39. }
  40. final boolean acquireQueued(final Node node, int arg) {
  41. boolean failed = true;
  42. try {
  43. boolean interrupted = false;
  44. for (;;) {
  45. final Node p = node.predecessor();//获取前一个节点
  46. if (p == head && tryAcquire(arg)) {//前一个节点为头节点,且获取同步状态
  47. setHead(node);
  48. p.next = null; // help GC
  49. failed = false;
  50. return interrupted;
  51. }
  52. if (shouldParkAfterFailedAcquire(p, node) &&
  53. parkAndCheckInterrupt())//线程进入等待状态
  54. interrupted = true;
  55. }
  56. } finally {
  57. if (failed)
  58. cancelAcquire(node);
  59. }
  60. }
  61. private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
  62. int ws = pred.waitStatus;//前一个节点的状态
  63. if (ws == Node.SIGNAL)
  64. /*
  65. * This node has already set status asking a release
  66. * to signal it, so it can safely park.
  67. */
  68. return true;
  69. if (ws > 0) {
  70. /*
  71. * Predecessor was cancelled. Skip over predecessors and
  72. * indicate retry.
  73. */
  74. do {
  75. node.prev = pred = pred.prev;
  76. } while (pred.waitStatus > 0);
  77. pred.next = node;
  78. } else {
  79. /*
  80. * waitStatus must be 0 or PROPAGATE. Indicate that we
  81. * need a signal, but don't park yet. Caller will need to
  82. * retry to make sure it cannot acquire before parking.
  83. */
  84. compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
  85. }
  86. return false;
  87. }
  1. public final boolean release(int arg) {
  2. if (tryRelease(arg)) {
  3. Node h = head;
  4. if (h != null && h.waitStatus != 0)
  5. unparkSuccessor(h);
  6. return true;
  7. }
  8. return false;
  9. }
  10. private void unparkSuccessor(Node node) {
  11. /*
  12. * If status is negative (i.e., possibly needing signal) try
  13. * to clear in anticipation of signalling. It is OK if this
  14. * fails or if status is changed by waiting thread.
  15. */
  16. int ws = node.waitStatus;
  17. if (ws < 0)
  18. compareAndSetWaitStatus(node, ws, 0);
  19. /*
  20. * Thread to unpark is held in successor, which is normally
  21. * just the next node. But if cancelled or apparently null,
  22. * traverse backwards from tail to find the actual
  23. * non-cancelled successor.
  24. */
  25. Node s = node.next;
  26. if (s == null || s.waitStatus > 0) {
  27. s = null;
  28. for (Node t = tail; t != null && t != node; t = t.prev)
  29. if (t.waitStatus <= 0)
  30. s = t;
  31. }
  32. if (s != null)
  33. LockSupport.unpark(s.thread);
  34. }

具体流程图在Java并发编程的艺术P128页

共享式同步状态获取与释放

共享式同步状态获取与释放最主要的区别在于同一时刻能否有多个线程同时获取到同步状态。

  1. //尝试获取同步状态,当返回值大于等于0时,表示可以获取同步状态
  2. public final void acquireShared(int arg) {
  3. if (tryAcquireShared(arg) < 0)
  4. doAcquireShared(arg);
  5. }
  6. //需要自己实现
  7. protected int tryAcquireShared(int arg) {
  8. throw new UnsupportedOperationException();
  9. }
  10. private void doAcquireShared(int arg) {
  11. final Node node = addWaiter(Node.SHARED);//创建节点,并且添加到末尾,且返回节点
  12. boolean failed = true;
  13. try {
  14. boolean interrupted = false;
  15. for (;;) {
  16. final Node p = node.predecessor();//获取该节点前一个节点
  17. if (p == head) {//前一个节点为头节点
  18. int r = tryAcquireShared(arg);//获取同步状态
  19. if (r >= 0) {//获取成功
  20. setHeadAndPropagate(node, r);//修改头节点
  21. p.next = null; // help GC
  22. if (interrupted)
  23. selfInterrupt();
  24. failed = false;
  25. return;
  26. }
  27. }
  28. if (shouldParkAfterFailedAcquire(p, node) &&
  29. parkAndCheckInterrupt())
  30. interrupted = true;
  31. }
  32. } finally {
  33. if (failed)
  34. cancelAcquire(node);
  35. }
  36. }

Condition的实现与分析

  1. //初始节点
  2. private transient Node firstWaiter;
  3. //尾节点
  4. private transient Node lastWaiter;
  5. //将以当前线程构造节点,并将节点从尾部加入等待队列
  6. //不需要CAS保证,因为调用await()方法的线程必定是获取了锁的线程
  7. public final void await() throws InterruptedException {
  8. if (Thread.interrupted())
  9. throw new InterruptedException();
  10. Node node = addConditionWaiter();
  11. int savedState = fullyRelease(node);
  12. int interruptMode = 0;
  13. while (!isOnSyncQueue(node)) {
  14. LockSupport.park(this);
  15. if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
  16. break;
  17. }
  18. if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
  19. interruptMode = REINTERRUPT;
  20. if (node.nextWaiter != null) // clean up if cancelled
  21. unlinkCancelledWaiters();
  22. if (interruptMode != 0)
  23. reportInterruptAfterWait(interruptMode);
  24. }

未完待续。。。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注