通过Lock对象以及Condition对象实现多线程同步

在之前的学习中,无论是通过synchronized建立同步代码块,还是通过synchronized建立同步函数,都是把对象看成一把锁来实现同步,这种解释有点牵强,而且在消费者—生产者的那个实例中,其实还有个问题,那就是在避免线程全部冻结时,没必要把相同功能的线程解冻,只要把其他功能的线程解冻即可,也就是说消费者线程只要解冻生产者线程即可,没必要把其他消费者线程也解冻,为了解决这些问题,java1.5版本推出了同步的升级办法,那就是通过Lock对象和Condition对象实现同步。

新的同步办法不再需要synchronized关键字,而引入了更加形象的Lock。

Lock实质上是是一个接口,在创建对象时,使用Lock的子类ReentrantLock来建立对象。

使用方法:建立对象后,在需要同步的代码前一行写    Lock对象.lock();   ,在同步代码后一行写   Lock对象.unlock();

Lock对象用来控制线程的进出,而对线程的操作则由Condition对象来操作;

对应关系:

wait——await(两者均抛出异常)

notify——signal

notifyAll——signalAll

Condition同样是接口,建立方法(比较神奇)       Condition 对象名=Lock对象.newCondition();

例如:1-9 个数,A线程执行123.然后由B线程接着执行456.最后在由A线程执行789

代码:

  1. package com.huojg.test;
  2.  
  3. import java.util.concurrent.locks.Condition;
  4. import java.util.concurrent.locks.Lock;
  5. import java.util.concurrent.locks.ReentrantLock;
  6.  
  7. /*
  8. *
  9. * 1-9 个数,A线程执行123.然后由B线程接着执行456.最后在由A线程执行789
  10. *
  11. *
  12. * **/
  13. public class lock {
  14. static class NumberWrapper {
  15. public int value = 1;
  16. }
  17.  
  18. public static void main(String[] args) {
  19.  
  20. //初始化可重入锁
  21. final Lock lock=new ReentrantLock();
  22. //第一个条件当屏幕上输出到3
  23. final Condition reachThreeCondition=lock.newCondition();
  24. //第一个条件当屏幕上输出到6
  25. final Condition reachSixCondition=lock.newCondition();
  26. //NumberWrapper只是为了封装一个数字,一边可以将数字对象共享,并可以设置为final
  27. //注意这里不要用Integer, Integer 是不可变对象
  28. final NumberWrapper num = new NumberWrapper();
  29. //初始化A线程
  30. Thread threadA=new Thread( new Runnable() {
  31. public void run() {
  32. //需要先获得锁
  33. lock.lock();
  34. try {
  35. System.out.println("threadA start write");
  36. while (num.value<=3) {
  37. System.out.println(num.value);
  38. num.value++;
  39. }
  40. //输出到3时要signal,告诉B线程可以开始了
  41. reachThreeCondition.signal();
  42. } finally{
  43. lock.unlock();
  44. }
  45.  
  46. lock.lock();
  47. try {
  48. //等待输出6的条件
  49. reachSixCondition.await();
  50. System.out.println("threadA start write");
  51. //输出剩余数字
  52. while (num.value <= 9) {
  53. System.out.println(num.value);
  54. num.value++;
  55. }
  56. } catch (InterruptedException e) {
  57. e.printStackTrace();
  58. } finally {
  59. lock.unlock();
  60. }
  61. }
  62. });
  63.  
  64. Thread threadB =new Thread(new Runnable() {
  65. public void run() {
  66. try {
  67. lock.lock();
  68. while (num.value<=3) {
  69. //等待3输出完毕的信号
  70. reachThreeCondition.await();
  71. }
  72.  
  73. }catch (InterruptedException e) {
  74. e.printStackTrace();
  75. } finally {
  76. lock.unlock();
  77. }
  78.  
  79. try {
  80. lock.lock();
  81. //已经收到信号,开始输出4,5,6
  82. System.out.println("threadB start write");
  83. while (num.value <= 6) {
  84. System.out.println(num.value);
  85. num.value++;
  86. }
  87. //4,5,6输出完毕,告诉A线程6输出完了
  88. reachSixCondition.signal();
  89.  
  90. } finally{
  91. lock.unlock();
  92. }
  93.  
  94. }
  95. });
  96.  
  97. //启动两个线程
  98. threadB.start();
  99. threadA.start();
  100.  
  101. }
  102.  
  103. }

结果:

  1. threadA start write
  2. 1
  3. 2
  4. 3
  5. threadB start write
  6. 4
  7. 5
  8. 6
  9. threadA start write
  10. 7
  11. 8
  12. 9

  

Condition对象的优势在于,signal只能唤醒被相同Condition对象的await方法冻结的线程,因此,可以建立多个Condition对象,分别用来冻结和解冻不同功能的线程

最后要注意的是,Lock接口属于类包Java.util.concurrent.locks

通过Lock对象以及Condition对象实现多线程同步的更多相关文章

  1. 孤荷凌寒自学python第四十二天python线程控制之Condition对象

     孤荷凌寒自学python第四十二天python的线程同步之Condition对象 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 今天学习了Condition对象,发现它综合了Event对象 ...

  2. java高并发系列 - 第13天:JUC中的Condition对象

    本文目标: synchronized中实现线程等待和唤醒 Condition简介及常用方法介绍及相关示例 使用Condition实现生产者消费者 使用Condition实现同步阻塞队列 Object对 ...

  3. Lock锁与Condition监视器(生产者与消费者)。

    /*生产者与消费者第二次敲,本人表示很郁闷,以后要经常读这个 * Condition 将Object类中的监视器(wait notify notifyAll)分解成不同的对象.例如condition_ ...

  4. 多线程模块的condition对象

    Python提供的Condition对象提供了对复杂线程同步问题的支持.Condition被称为条件变量,除了提供与Lock类似的acquire和release方法外,还提供了wait和notify方 ...

  5. jdk1.5多线程Lock接口及Condition接口

    jdk1.5多线程的实现的方式: jdk1.5之前对锁的操作是隐式的 synchronized(对象) //获取锁 { } //释放锁 jdk1.5锁的操作是显示的:在包java.util.concu ...

  6. Condition对象以及ArrayBlockingQueue阻塞队列的实现(使用Condition在队满时让生产者线程等待, 在队空时让消费者线程等待)

    Condition对象 一).Condition的定义 Condition对象:与锁关联,协调多线程间的复杂协作. 获取与锁绑定的Condition对象: Lock lock = new Reentr ...

  7. 并发、并行、同步、异步、全局解释锁GIL、同步锁Lock、死锁、递归锁、同步对象/条件、信号量、队列、生产者消费者、多进程模块、进程的调用、Process类、

    并发:是指系统具有处理多个任务/动作的能力. 并行:是指系统具有同时处理多个任务/动作的能力. 并行是并发的子集. 同步:当进程执行到一个IO(等待外部数据)的时候. 异步:当进程执行到一个IO不等到 ...

  8. Windows多线程同步系列之一-----互斥对象

    多线程同步之互斥对象 作者:vpoet mail:vpoet_sir@163.com   对卖票问题进行线程间同步,本文将在上文的基础上,使用互斥对象对线程进行同步. 首先看看windows API ...

  9. [多线程]线程基础(对象锁、class锁、同步、异步)

    synchronized.volatile.ReentrantLock.concurrent 线程安全:当多个线程访问某一个类(对象或方法)时,这个类始终都能表现出正确的行为,那么这个类(对象或方法) ...

随机推荐

  1. 彗星撞地球 | 近25万倍压缩的精品3D动画

    文章目录 写在前面 Prophecy<彗星撞地球> 下载地址 简概 注意 3D射击小游戏 下载地址 简概 写在前面 WareZ是个无形的组织,号称"不以赢利为目的纯技术团体&qu ...

  2. ThinkPHP中实例化对象M()和D()的区别

    ThinkPHP中实例化对象M()和D()的区别 ThinkPHP中实例化对象M()和D()的区别?ThinkPHP如何实例化对象?在实例化的过程中,经常使用D方法和M方法,这两个方法的区别在于M方法 ...

  3. MySQL四种类型日志:Error Log、General Query Log、Binary Log、Slow Query Log

    MySQL Server 有四种类型的日志——Error Log.General Query Log.Binary Log 和 Slow Query Log. 第一个是错误日志,记录mysqld的一些 ...

  4. ios中调用WCF

    例子比较简单 记录下思路 1.接口中定义 实体和方法声明 //登录信息        [OperationContract]        [WebInvoke(UriTemplate = " ...

  5. JS 随机数字抽签

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <t ...

  6. 彻底解决DZ大附件上传问题

    个. 注意:很多人遇到修改php.ini后重应WEB服务后仍然不能生效.这种情况应该先确认一下所改的php.ini是不是当前PHP所使用的.您可以在WEB目录下建立一个php文件,内容很简单就一句话& ...

  7. 使用echarts简单制作中国地图,echarts中国地图

    网站需要一张中国地图,并且鼠标经过某个省份,该省份的省份名字显示,而且该省份的地区会变色显示. 第一种方法: 将每个省份的图片定位(先隐藏),拼合成一张中国地图,然后再定位省份名称,鼠标经过省份名字, ...

  8. bind域名dns解析及主从服务的配置

    bind域名dns解析及主从服务的配置 1.dns解析介绍     人们习惯记忆域名,但机器间互相只认IP地址,域名与IP地址之间是多对一的关系,一个ip地址不一定只对应一个域名,且一个域名只可以对应 ...

  9. mvn 更改打包的名称

    在pom.xml中加入以下代码 <build> <finalName>moon</finalName> <pluginManagement> <p ...

  10. android项目 之 记事本(13) ----- 查看图片及播放录音

    本文是自己学习所做笔记,欢迎转载.但请注明出处:http://blog.csdn.net/jesson20121020 今天就来实现下查看图片及录音的功能,在编辑或者浏览记事时,点击图片.打开一个自己 ...