`

Condition

 
阅读更多

A线程在使用Lock获得锁的后,可能会由于某些条件不满足,而不能继续执行,需要等待条件满足时,可以使用 Condition,Lock接口有一个newCondition()方法实化Condition,调用 Condition.await()当前线程释放锁,进入阻塞状态,当B线程获得这个锁并使条件满足时,调用同一个Condition实例的notify或notifyAll方法时,A线程被唤醒,但并未执行,需要B线程释放锁之后,A线程能够得到锁,才从await之后的代码执行。 

 

A线程调用Condition.await()方法之后,

如果A线程在进入await方法之前被中断,await立即返回,抛出InterruptedException

否则进入阻塞状态,A线程被唤醒的条件:

  1.同一个Condition实例的notifyAll被调用

  2.同一个Condition实例的notify被调用,碰巧将A线程选为被唤醒的线程

  4.有可能产生”虚假唤醒“

 

由于A线程可能是被”虚假唤醒“的,则此await方需在一个循环块中检测条件是否满足。

 

A线程被唤醒后,需要获得Lock才能执行后续程序, 未能获得LOCK则继续阻塞。

 

如果A线程阻塞过程中,被其它线程中断,那么唤醒并获得锁后,await方法抛出InterruptedException, 

如果A线程被唤醒之后,获得锁之前,被其它线程中断,则调用设标中断标志,Thread.currentThread().interrupt();

 

方法:

 

 

 void

await() 
          造成当前线程在接到信号或被中断之前一直处于等待状态。

         有可能被“虚假唤醒" 需要在循环中使用

 boolean

await(long time, TimeUnit unit) 
          造成当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态。

有可能被“虚假唤醒" 需要在循环中使用

 long

awaitNanos(long nanosTimeout) 
          造成当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态。

 

 void awaitUninterruptibly() 
          造成当前线程在接到信号之前一直处于等待状态。
 boolean awaitUntil(Date deadline) 
          造成当前线程在接到信号、被中断或到达指定最后期限之前一直处于等待状态。
 void signal() 
          唤醒一个等待线程。
 void signalAll() 
          唤醒所有等待线程。

 

 

java API中给出的示例:

 class BoundedBuffer {
   final Lock lock = new ReentrantLock();
   final Condition notFull  = lock.newCondition(); 
   final Condition notEmpty = lock.newCondition(); 

   final Object[] items = new Object[100];
   int putptr, takeptr, count;

   public void put(Object x) throws InterruptedException {
     lock.lock();
     try {
       while (count == items.length) 
         notFull.await();
       items[putptr] = x; 
       if (++putptr == items.length) putptr = 0;
       ++count;
       notEmpty.signal();
     } finally {
       lock.unlock();
     }
   }

   public Object take() throws InterruptedException {
     lock.lock();
     try {
       while (count == 0) 
         notEmpty.await();
       Object x = items[takeptr]; 
       if (++takeptr == items.length) takeptr = 0;
       --count;
       notFull.signal();
       return x;
     } finally {
       lock.unlock();
     }
   } 
 }

 

 源码分析:

  await方法:

 public final void await() throws InterruptedException {
            if (Thread.interrupted())
                throw new InterruptedException();//刚进入方法时如果有中断,抛出异常
            Node node = addConditionWaiter();//新生成一个等待节点
            int savedState = fullyRelease(node);//释放多层锁
            int interruptMode = 0;
            while (!isOnSyncQueue(node)) {//此节点未在同步节点队列中,isOnSyncQueue会返回假,直至signal被调用时才加入到队列中跳出循环
                LockSupport.park(this);//线程阻塞,线程可能被”虚假唤醒“因此需要循环
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;//线程被唤醒后,监测线程中断标志, 发生中断则把node存入同步节点队列 ,跳出循环
            }
  //将节点存入同步节点队列目的是按队列顺序获得锁
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)//acquireQueued方法内存是个死循环,直至获得锁才返回,未获得锁就继续阻塞
                interruptMode = REINTERRUPT;
            if (node.nextWaiter != null)
                unlinkCancelledWaiters();
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);//发生中断抛出异常或设置中断标志
        }

 

 

  

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics