通过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. LRC的效验码的计算方法

    图一中需要检验ASCI码数据是30.31.30.30.30.30.30.30,转化为16进制累加后是0000 0001,取反加1得到1111 1111,转换为ASCI码46.46.和图中是一样的. 图 ...

  2. 教育 z

    奥巴马母亲留给儿子的遗产,不是谎言,而是让反对派不敢戮辨的——伟大的人格及优秀! 相比于奥巴马的母亲,中国式父母,更愿意走省心的路子.给孩子最催肥的食物,最昂贵的衣物,最庸懒的生活环境,不让孩子做任何 ...

  3. JAVA常见算法题(三)

    package com.xiaowu.demo; //打印出所有的"水仙花数",所谓"水仙花数"是指一个三位数,其各位数字立方和等于该数本身. //例如:153 ...

  4. django admin后台编辑页面 显示数据公式

    先用django markdownx进行实时预览, 然后在 /Library/Python/2.7/site-packages/django/contrib/admin 这个目录下,加入 <sc ...

  5. android Broadcast 总结

    1, 生命周期 在android官方文档中,推荐我们在onResume中进行 registerReceiver, 在onPause中进行unRegisterReceiver. 他们给出的理由是: If ...

  6. Linux如何查找大文件

    https://www.cnblogs.com/kerrycode/p/4391859.html find . -type f -size +800M 如上命令所示,我们仅仅能看到超过800M大小的文 ...

  7. php不重新编译添加模块

    php不重新编译添加模块 本文以安装mysqli模块为例 一.检查 1:首先保证php-fpm能正常启动 2:查看当前已安装的php模块是否有mysqli [root@web01 ~]# /appli ...

  8. 联想T470设置U盘启动

    联想T470设置U盘启动 学习了:http://www.udaxia.com/upqd/10092.html # F12 in Enter in USB HDD 如果不行: App Menu > ...

  9. WIN7 安装其他的系统boot

    1,安装win7系统不赘述. 2,在安装完win7系统后,准备安装CentOS7.0 3,准备ISO文件和所需软件 1.CentOS官网下载DVD ISO文件​ 一般选择DVD ISO ​     2 ...

  10. Gentoo:startx出现Failed to load module问题

    安装完xorg-server后,startx启动桌面环境,出现缺少模块错误. 查看log: cat /var/log/Xorg.0.log | grep EE [75.403] (EE) Failed ...