当前位置:首页 > 开发 > 编程语言 > 多线程 > 正文

Condition 条件变量,线程通信更高效的方式

发表于: 2014-02-19   作者:cuisuqiang   来源:转载   浏览次数:
摘要: 条件(也称为条件队列 或条件变量)为线程提供了一个含义,以便在某个状态条件现在可能为 true 的另一个线程通知它之前,一直挂起该线程(即让其“等待”)。因为访问此共享状态信息发生在不同的线程中,所以它必须受保护,因此要将某种形式的锁与该条件相关联。等待提供一个条件的主要属性是:以原子方式 释放相关的锁,并挂起当前线程,就像 Object.wait 做的那样   在Condition

条件(也称为条件队列 或条件变量)为线程提供了一个含义,以便在某个状态条件现在可能为 true 的另一个线程通知它之前,一直挂起该线程(即让其“等待”)。因为访问此共享状态信息发生在不同的线程中,所以它必须受保护,因此要将某种形式的锁与该条件相关联。等待提供一个条件的主要属性是:以原子方式 释放相关的锁,并挂起当前线程,就像 Object.wait 做的那样

 

在Condition中,用await()替换wait(),用signal()替换notify(),用signalAll()替换notifyAll(),传统线程的通信方式,Condition都可以实现。
条件变量类似JDK1.4或以前版本中的 Object.wait(); Object.notify(); Object.notifyAll();
值得注意的是当condition.await()时,隐式的将条件变量关联的Lock解锁,而使其他线程有机会获得Lock,而检查条件,并在条件满足时,等待在条件变量上。

 

示例代码,ArrayBlockingQueue源码摘取:

/** Main lock guarding all access */
private final ReentrantLock lock;
/** Condition for waiting takes */
private final Condition notEmpty;
/** Condition for waiting puts */
private final Condition notFull;
/**
 * Inserts the specified element at the tail of this queue, waiting
 * for space to become available if the queue is full.
 *
 * @throws InterruptedException {@inheritDoc}
 * @throws NullPointerException {@inheritDoc}
 */
public void put(E e) throws InterruptedException {
 if (e == null) throw new NullPointerException();
 final E[] items = this.items;
 final ReentrantLock lock = this.lock;
 lock.lockInterruptibly();
 try {
  try {
   while (count == items.length)
    notFull.await();
  } catch (InterruptedException ie) {
   notFull.signal(); // propagate to non-interrupted thread
   throw ie;
  }
  insert(e);
 } finally {
  lock.unlock();
 }
}
public E take() throws InterruptedException {
 final ReentrantLock lock = this.lock;
 lock.lockInterruptibly();
 try {
  try {
   while (count == 0)
    notEmpty.await();
  } catch (InterruptedException ie) {
   notEmpty.signal(); // propagate to non-interrupted thread
   throw ie;
  }
  E x = extract();
  return x;
 } finally {
  lock.unlock();
 }
}

 

有多个线程往里面存数据和从里面取数据,其队列(先进先出后进后出)能缓存的最大数值是capacity,多个线程间是互斥的,当缓存队列中存储的值达到capacity时,将写线程阻塞,并唤醒读线程,当缓存队列中存储的值为0时,将读线程阻塞,并唤醒写线程
这就是多个Condition的强大之处,假设缓存队列中已经存满,那么阻塞的肯定是写线程,唤醒的肯定是读线程,相反,阻塞的肯定是读线程,唤醒的肯定是写线程,那么假设只有一个Condition会有什么效果呢,缓存队列中已经存满,这个Lock不知道唤醒的是读线程还是写线程了,如果唤醒的是读线程,皆大欢喜,如果唤醒的是写线程,那么线程刚被唤醒,又被阻塞了,这时又去唤醒,这样就浪费了很多时间!

 

请您到ITEYE网站看 java小强 原创,谢谢!

http://cuisuqiang.iteye.com/ 

自建博客地址:http://www.javacui.com/ ,内容与ITEYE同步!

Condition 条件变量,线程通信更高效的方式

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
Condition是Locks锁下的还有一种线程通信之间唤醒、堵塞的实现。它以下的await,和signal可以实现Obj
Java5 中提过了Condition ,该类可以实现线程间的条件控制,废话少说直接来看一个实例。 实例: 启
Lock和Condition是为了替代synchroinzed、wait、notify的,有点是更面向对象,功能上也更强大。下面
为避免死锁,就应该让线程在进入阻塞状态时尽量释放其锁定的资源,以为其他的线程提供运行的机会,O
1 -- 关于pthread条件变量 man pthread_cond_init | col -b > pthread_cond.man得到manual中的描
1.条件变量和mutex到底有什么区别?都是在没有拿锁的情况下阻塞,拿到锁了解除阻塞。那为什么还要用
  为了允许在线程或进程之间共享数据,同步时必须的,互斥锁和条件变量是同步的基本组成部分。 1
这是来自于Smile的投稿,很实战的和大家分享了高效的思维方式,如果大家感兴趣,可以和他直接交流。
MySQL5.6.7-rc index condition pushdown 索引条件下推代码解读 http://jishu.zol.com.cn/4505.html
andriod提供了 Handler 和 Looper 来满足线程间的通信。例如一个子线程从网络上下载了一副图片,当
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号