J.U.C — Locks — ReentrantLock(二)

来源:互联网 发布:服装设计要学什么软件 编辑:程序博客网 时间:2024/06/10 18:46

条件变量Condition

Condition实现了synchronized同步器的wait/notify/notifyAll的功能,Condition接口提供的API如下:


Condition需要与Lock绑定,一个Lock可以有多个Condition,获取Condition的方式是lock.newCondition()。Condition的实现类在AQS中的ConditionObject,类部维持了一个等待队列:


  • 获取Condition
lock.newCondition() -->// ReentrantLockpublic Condition newCondition() {    return sync.newCondition();}// ReentrantLock.Syncfinal ConditionObject newCondition() {    return new ConditionObject();}                                -->                                // AQS.ConditionObject                                public ConditionObject() { }

  •  await()
public final void await() throws InterruptedException {                                                                   if (Thread.interrupted())     // 如果当前线程被终端,抛出异常                                                                       throw new InterruptedException();                                                                   Node node = addConditionWaiter();     // 1. 将当前线程添加到Condition队列                                                                   int savedState = fullyRelease(node);     // 2. 释放锁                                                                   int interruptMode = 0;                                                                   while (!isOnSyncQueue(node)) {     // 3. 自旋直到被signal或signalAll唤醒                                                                       LockSupport.park(this);     // 挂起当前线程                                                                       if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)                                                                           break;                                                                   }                                                                   if (acquireQueued(node, savedState) && interruptMode != THROW_IE)    // 4. 自旋去获取锁                                                                       interruptMode = REINTERRUPT;                                                                   if (node.nextWaiter != null) // clean up if cancelled                                                                       unlinkCancelledWaiters();                                                                   if (interruptMode != 0)                                                                       reportInterruptAfterWait(interruptMode);                                                               }                                                               // 1.                                                               private Node addConditionWaiter() {                                                                   Node t = lastWaiter;                                                                   // If lastWaiter is cancelled, clean out.                                                                   if (t != null && t.waitStatus != Node.CONDITION) {                                                                       unlinkCancelledWaiters();                                                                       t = lastWaiter;                                                                   }                                                                   Node node = new Node(Thread.currentThread(), Node.CONDITION);                                                                   if (t == null)                                                                       firstWaiter = node;                                                                   else                                                                       t.nextWaiter = node;                                                                   lastWaiter = node;                                                                   return node;                                                               }                                                               // 2.                                                               final int fullyRelease(Node node) {                                                                   boolean failed = true;                                                                   try {                                                                       int savedState = getState();                                                                       if (release(savedState)) {     // 调用release方法释放锁                                                                           failed = false;                                                                           return savedState;                                                                       } else {                                                                           throw new IllegalMonitorStateException();                                                                       }                                                                   } finally {                                                                       if (failed)                                                                           node.waitStatus = Node.CANCELLED;                                                                   }                                                               }                                                               // 3.                                                               final boolean isOnSyncQueue(Node node) {                                                                   if (node.waitStatus == Node.CONDITION || node.prev == null)                                                                       return false;                                                                   if (node.next != null) // If has successor, it must be on queue                                                                       return true;                                                                   return findNodeFromTail(node);                                                               }                                                               private boolean findNodeFromTail(Node node) {     // 在sync队列中从尾部到头部查找是不是在sync队列中                                                                   Node t = tail;                                                                   for (;;) {                                                                       if (t == node)                                                                           return true;                                                                       if (t == null)                                                                           return false;                                                                       t = t.prev;                                                                   }                                                               }

  • signal()
public final void signal() {                                                                  if (!isHeldExclusively())     // 1. 判断是不是当前线程持有锁,只有持有锁的线程能唤醒其他等待的线程                                                                      throw new IllegalMonitorStateException();                                                                  Node first = firstWaiter;                                                                  if (first != null)                                                                     doSignal(first);     // 2. 通知Condition队列中的等待最长时间的线程,即firstWaiter                                                               }// ReentrantLock.Sync// 1.protected final boolean isHeldExclusively() {    return getExclusiveOwnerThread() == Thread.currentThread();}                                                                       // 2.                                                                       private void doSignal(Node first) {                                                                           do {                                                                               if ( (firstWaiter = first.nextWaiter) == null)                                                                                   lastWaiter = null;                                                                               first.nextWaiter = null;                                                                           } while (!transferForSignal(first) &&                                                                                   (first = firstWaiter) != null);                                                                       }                                                                       final boolean transferForSignal(Node node) {                                                                           if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))                                                                               return false;                                                                           Node p = enq(node);     // 将节点加入sync队列                                                                           int ws = p.waitStatus;                                                                           if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))                                                                               LockSupport.unpark(node.thread);                                                                           return true;                                                                       }

事例

假设现在有三个线程陆续调用同一个condition的await
  • 开始状态:thread-1获取锁

    1. thread-1调用await():
                   用thread-1创建节点,并设置waitStatus= -2(Condition),再将thread-1加入Condition队列,队列为空,将firstWaiter和lastWaiter设为thread-1;
                   调用release释放thread-1拥有的锁,并从Sync队列中移除节点;
                   自旋等待唤醒

  • thread-2调用await():

  • thread-3调用await():

  •  当收到signal信号后,会从condition队列中从头开始将节点移到sync队列,并唤醒自旋获取锁
0 0
原创粉丝点击