听说过条件变量Condition吗

上一次我们介绍了ReentrantLock和Synchronized的异同,这次我们来讲讲concurrent包下面的另外一个类,Condition。 Java的 java.util.concurrent 包提供了很多处理并发场景的类,Condition 就是其中一个。

我们花三分钟来了解Condition的作用吧~

场景举例

现在有个队列,线程A和线程B同时往里面写数据。 A从1写到3,B从4写到6,再交给A从7写到10,这样的场景我们要怎么处理问题呢?

首先想到的是并发加锁处理,然后就是我们要介绍的Condition了!

//初始化锁
final Lock lock = new ReentrantLock();

//第一个条件当A写到3
final Condition reachThreeCondition = lock.newCondition();
//第二个条件当B写到6
final Condition reachSixCondition = lock.newCondition();

获取Condition对象的方法很简单,对锁进行newCondition()操作就可以。 我们直接以 ThreadA 举例,B的逻辑也是一样的。

Thread threadA = new Thread(new Runnable() {
  @Override
  public void run() {
      //需要先获得锁
      lock.lock();
      try {
          System.out.println("threadA start write");
          //A线程先写前3个数
          ...
          //输出到3时要signal,告诉B线程可以开始了
          reachThreeCondition.signal(); <====
      } finally {
          lock.unlock();
      }
      lock.lock();
      try {
          //等待B写到6的条件
          reachSixCondition.await(); <====
          System.out.println("threadA start write");
          //写剩余数字
          ...
      } catch (InterruptedException e) {
          e.printStackTrace();
      } finally {
          lock.unlock();
      }
  }

  });

B线程

Thread threadB = new Thread(new Runnable() {
  @Override
  public void run() {
      try {
          lock.lock();

          while (num.value <= 3) {
              //等待3写完的信号
              reachThreeCondition.await(); <====
          }
      } catch (InterruptedException e) {
          e.printStackTrace();
      } finally {
          lock.unlock();
      }
      try {
          lock.lock();
          //已经收到信号,开始写4,5,6
          System.out.println("threadB start write");
          ...
          //4,5,6写完,告诉A线程
          reachSixCondition.signal(); <====
      } finally {
          lock.unlock();
      }
  }

  });
代码解析

代码很简单, · 当我们需要某个条件满足才继续往下执行时,调用Condition的await()方法, 此时线程会挂起,同时释放锁; · 其他并发线程完成条件后调用Condition的singnal()方法, 其他等待这个Condition的线程则会获取锁并继续往下执行。

总结

当处理并发场景且需要等待某种条件时,一般都会将Condition对象作为成员变量。当调用await()方法后,当前线程会释放锁并在此等待,而其他线程调用Condition对象的signal()方法,通知当前线程后,当前线程才从await()方法返回,并且在返回前已经获取了锁。

聪明的你肯定意识到Condition和BlockingQueue会有某种联系。是的阻塞队列BlockingQueue的原理就是基于Condition实现的

我们下一次继续介绍BlockingQueue吧! 欢迎关注订阅!

原文发布于微信公众号 - Android每日一讲(gh_f053f29083b9)

原文发表时间:2018-02-26

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏安恒网络空间安全讲武堂

[Web安全]PHP伪协议

[Web安全]PHP伪协议 最近php伪协议的各种神奇妙用好像突然又常常提到了,php中支持的伪协议有下面这么多 复制代码 file:// — 访问本地文件...

64380
来自专栏大闲人柴毛毛

轻量级线程池的实现

写在前面 最近因为项目需要,自己写了个单生产者-多消费者的消息队列模型。多线程真的不是等闲之辈能玩儿的,我花了两个小时进行设计与编码,却花了两天的时间调试与运...

54740
来自专栏JackeyGao的博客

用户Python3解析超大的csv文件

我在日前获得一个任务,为了做分析, 从一个超大的csv文件中解析email地址和对应的日期时间戳然后插入到数据库中. 我知道有其他工具可以方便的完成我的工作(比...

12120
来自专栏FreeBuf

Windows内核漏洞CVE-2016-0143分析

0x00 背景 4月20日,Nils Sommer在exploitdb上爆出了一枚新的Windows内核漏洞PoC。该漏洞影响所有版本的Windows操作系统,...

24360
来自专栏安恒网络空间安全讲武堂

从零基础到成功解题之0ctf-ezdoor

22340
来自专栏前端达人

JavaScript基础——回调(callback)是什么

上篇文章《JavaScript基础——你真的了解JavaScript吗?》,我们明白了JavaScript是一个单线程、非阻塞、异步、解释性语言,清楚了什么是单...

26670
来自专栏农夫安全

代码审计之命令执行漏洞

环境:windows + apache + mysql + php (phpstudy) 由于是在Windows下进行的测试,所以和Linux下的测试会有所不...

29460
来自专栏西枫里博客

TP5中paginate方法丢失url参数的问题

一个简单的应用场景。现在需要在后台对用户产品数据进行搜索,可以对产品名称使用模糊检索,也可以使用产品类别进行分类搜索。因为搜索条件是两个表单项,所以简单了区分搜...

7710
来自专栏运维一切

ceph对象存储折腾记 原

###前言 一直想弄对象存储,以前弄过一次,不是很理解region是个什么东西,后来时间和工作上的原因没有再折腾,这两天闲了下来,再次折腾了一次。我是参考的ce...

18410
来自专栏大内老A

如何让普通变量也支持事务回滚?

有一次和人谈起关于事务的话题,谈到怎样的资源才能事务型资源。除了我们经常使用的数据库、消息队列、事务型文件系统(TxF)以及事务性注册表(TxR)等,还有那些资...

19080

扫码关注云+社区

领取腾讯云代金券