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);//发生中断抛出异常或设置中断标志
        }

 

 

  

 

<think>好的,用户想了解JavaCondition接口的用法和相关编程问题。首先,我需要回忆一下Condition接口的基本概念和它在Java并发编程中的作用。Condition接口通常与Lock配合使用,用于实现线程间的协调,类似于Object类的wait()、notify()和notifyAll()方法,但提供了更灵活的功能。 接下来,我应该整理Condition的主要方法,比如await()、signal()和signalAll(),并说明它们与传统wait/notify的区别。用户可能需要知道为什么使用Condition而不是内置的监视器方法,所以需要强调Condition的优点,比如多个等待集、更细粒度的控制等。 然后,考虑一个实际的使用示例。例如,实现一个简单的有界队列,当队列满时,生产者线程等待;当队列空时,消费者线程等待。这可以展示如何用Conditionawait和signal来管理线程的等待和唤醒。编写代码时要注意锁的正确获取和释放,以及处理InterruptedException的情况。 同时,用户可能对Condition的使用场景和最佳实践感兴趣,需要解释什么时候应该选择Condition,比如在复杂的同步结构中,或者需要多个条件谓词时。此外,可能还需要提到常见的陷阱,比如忘记在finally块中释放锁,或者错误地使用signal而不是signalAll导致信号丢失。 还需要检查是否有相关的引用内容可以支持回答。查看提供的引用,引用[1]提到类的成员包括方法,引用[2]展示了线程持有对象的情况,可能与线程协调有关,引用[3]讨论了联合类型的参数判别,这可能与条件判断有关联。不过,这些引用可能与Condition接口的直接关联不大,但可以适当引用其中关于类成员或线程示例的部分来增强回答的可信度。 最后,生成相关问题,帮助用户进一步学习,比如Condition与wait/notify的区别,如何避免死锁,或者Condition在生产者-消费者模式中的应用。确保问题覆盖用户可能感兴趣的扩展话题,并引导他们深入理解。</think>### JavaCondition接口的用法详解 #### 1. Condition接口基础 Condition接口是`java.util.concurrent.locks`包中的核心组件,需配合`Lock`实现线程协调。与传统的`Object.wait()`/`notify()`相比,它支持**多个等待队列**,提供更细粒度的线程控制[^1]。 主要方法: - `await()`: 使当前线程等待并释放锁,可响应中断 - `signal()`: 唤醒一个等待线程 - `signalAll()`: 唤醒所有等待线程 #### 2. 标准使用模板 ```java Lock lock = new ReentrantLock(); Condition condition = lock.newCondition(); lock.lock(); try { while (条件不满足) { condition.await(); // 释放锁并等待 } // 执行操作 } finally { lock.unlock(); } ``` #### 3. 生产者-消费者案例 实现线程安全的阻塞队列: ```java class BoundedBuffer { final Lock lock = new ReentrantLock(); final Condition notFull = lock.newCondition(); final Condition notEmpty = lock.newCondition(); 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(); } } } ``` 此实现特点: 1. 使用两个独立Condition分别管理空/满状态 2. 避免虚假唤醒的`while`循环检查 3. 遵循`lock.unlock()`放在finally块的规范 #### 4. 关键优势 - **多条件谓词**:可为不同等待条件创建独立Condition对象 - **公平锁支持**:配合`ReentrantLock(true)`实现公平调度 - **超时机制**:提供`awaitNanos()`/`awaitUntil()`等超时方法 #### 5. 典型应用场景 - 线程池任务调度 - 阻塞队列实现 - 复杂状态机同步 - 资源访问控制(如数据库连接池) #### 6. 注意事项 - 始终在`lock()`和`unlock()`之间使用Condition - 调用signal时需持有对应的锁 - 推荐使用signalAll()避免信号丢失 - 处理InterruptedException时应维护线程中断状态
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值