通过Lock对象以及Condition对象实现多线程同步
通过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
代码:
- package com.huojg.test;
- import java.util.concurrent.locks.Condition;
- import java.util.concurrent.locks.Lock;
- import java.util.concurrent.locks.ReentrantLock;
- /*
- *
- * 1-9 个数,A线程执行123.然后由B线程接着执行456.最后在由A线程执行789
- *
- *
- * **/
- public class lock {
- static class NumberWrapper {
- public int value = 1;
- }
- public static void main(String[] args) {
- //初始化可重入锁
- final Lock lock=new ReentrantLock();
- //第一个条件当屏幕上输出到3
- final Condition reachThreeCondition=lock.newCondition();
- //第一个条件当屏幕上输出到6
- final Condition reachSixCondition=lock.newCondition();
- //NumberWrapper只是为了封装一个数字,一边可以将数字对象共享,并可以设置为final
- //注意这里不要用Integer, Integer 是不可变对象
- final NumberWrapper num = new NumberWrapper();
- //初始化A线程
- Thread threadA=new Thread( new Runnable() {
- public void run() {
- //需要先获得锁
- lock.lock();
- try {
- System.out.println("threadA start write");
- while (num.value<=3) {
- System.out.println(num.value);
- num.value++;
- }
- //输出到3时要signal,告诉B线程可以开始了
- reachThreeCondition.signal();
- } finally{
- lock.unlock();
- }
- lock.lock();
- try {
- //等待输出6的条件
- reachSixCondition.await();
- System.out.println("threadA start write");
- //输出剩余数字
- while (num.value <= 9) {
- System.out.println(num.value);
- num.value++;
- }
- } catch (InterruptedException e) {
- e.printStackTrace();
- } finally {
- lock.unlock();
- }
- }
- });
- Thread threadB =new Thread(new Runnable() {
- 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");
- while (num.value <= 6) {
- System.out.println(num.value);
- num.value++;
- }
- //4,5,6输出完毕,告诉A线程6输出完了
- reachSixCondition.signal();
- } finally{
- lock.unlock();
- }
- }
- });
- //启动两个线程
- threadB.start();
- threadA.start();
- }
- }
结果:
- threadA start write
- 1
- 2
- 3
- threadB start write
- 4
- 5
- 6
- threadA start write
- 7
- 8
- 9
Condition对象的优势在于,signal只能唤醒被相同Condition对象的await方法冻结的线程,因此,可以建立多个Condition对象,分别用来冻结和解冻不同功能的线程
最后要注意的是,Lock接口属于类包Java.util.concurrent.locks
通过Lock对象以及Condition对象实现多线程同步的更多相关文章
- 孤荷凌寒自学python第四十二天python线程控制之Condition对象
孤荷凌寒自学python第四十二天python的线程同步之Condition对象 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 今天学习了Condition对象,发现它综合了Event对象 ...
- java高并发系列 - 第13天:JUC中的Condition对象
本文目标: synchronized中实现线程等待和唤醒 Condition简介及常用方法介绍及相关示例 使用Condition实现生产者消费者 使用Condition实现同步阻塞队列 Object对 ...
- Lock锁与Condition监视器(生产者与消费者)。
/*生产者与消费者第二次敲,本人表示很郁闷,以后要经常读这个 * Condition 将Object类中的监视器(wait notify notifyAll)分解成不同的对象.例如condition_ ...
- 多线程模块的condition对象
Python提供的Condition对象提供了对复杂线程同步问题的支持.Condition被称为条件变量,除了提供与Lock类似的acquire和release方法外,还提供了wait和notify方 ...
- jdk1.5多线程Lock接口及Condition接口
jdk1.5多线程的实现的方式: jdk1.5之前对锁的操作是隐式的 synchronized(对象) //获取锁 { } //释放锁 jdk1.5锁的操作是显示的:在包java.util.concu ...
- Condition对象以及ArrayBlockingQueue阻塞队列的实现(使用Condition在队满时让生产者线程等待, 在队空时让消费者线程等待)
Condition对象 一).Condition的定义 Condition对象:与锁关联,协调多线程间的复杂协作. 获取与锁绑定的Condition对象: Lock lock = new Reentr ...
- 并发、并行、同步、异步、全局解释锁GIL、同步锁Lock、死锁、递归锁、同步对象/条件、信号量、队列、生产者消费者、多进程模块、进程的调用、Process类、
并发:是指系统具有处理多个任务/动作的能力. 并行:是指系统具有同时处理多个任务/动作的能力. 并行是并发的子集. 同步:当进程执行到一个IO(等待外部数据)的时候. 异步:当进程执行到一个IO不等到 ...
- Windows多线程同步系列之一-----互斥对象
多线程同步之互斥对象 作者:vpoet mail:vpoet_sir@163.com 对卖票问题进行线程间同步,本文将在上文的基础上,使用互斥对象对线程进行同步. 首先看看windows API ...
- [多线程]线程基础(对象锁、class锁、同步、异步)
synchronized.volatile.ReentrantLock.concurrent 线程安全:当多个线程访问某一个类(对象或方法)时,这个类始终都能表现出正确的行为,那么这个类(对象或方法) ...
随机推荐
- 彗星撞地球 | 近25万倍压缩的精品3D动画
文章目录 写在前面 Prophecy<彗星撞地球> 下载地址 简概 注意 3D射击小游戏 下载地址 简概 写在前面 WareZ是个无形的组织,号称"不以赢利为目的纯技术团体&qu ...
- ThinkPHP中实例化对象M()和D()的区别
ThinkPHP中实例化对象M()和D()的区别 ThinkPHP中实例化对象M()和D()的区别?ThinkPHP如何实例化对象?在实例化的过程中,经常使用D方法和M方法,这两个方法的区别在于M方法 ...
- MySQL四种类型日志:Error Log、General Query Log、Binary Log、Slow Query Log
MySQL Server 有四种类型的日志——Error Log.General Query Log.Binary Log 和 Slow Query Log. 第一个是错误日志,记录mysqld的一些 ...
- ios中调用WCF
例子比较简单 记录下思路 1.接口中定义 实体和方法声明 //登录信息 [OperationContract] [WebInvoke(UriTemplate = " ...
- JS 随机数字抽签
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <t ...
- 彻底解决DZ大附件上传问题
个. 注意:很多人遇到修改php.ini后重应WEB服务后仍然不能生效.这种情况应该先确认一下所改的php.ini是不是当前PHP所使用的.您可以在WEB目录下建立一个php文件,内容很简单就一句话& ...
- 使用echarts简单制作中国地图,echarts中国地图
网站需要一张中国地图,并且鼠标经过某个省份,该省份的省份名字显示,而且该省份的地区会变色显示. 第一种方法: 将每个省份的图片定位(先隐藏),拼合成一张中国地图,然后再定位省份名称,鼠标经过省份名字, ...
- bind域名dns解析及主从服务的配置
bind域名dns解析及主从服务的配置 1.dns解析介绍 人们习惯记忆域名,但机器间互相只认IP地址,域名与IP地址之间是多对一的关系,一个ip地址不一定只对应一个域名,且一个域名只可以对应 ...
- mvn 更改打包的名称
在pom.xml中加入以下代码 <build> <finalName>moon</finalName> <pluginManagement> <p ...
- android项目 之 记事本(13) ----- 查看图片及播放录音
本文是自己学习所做笔记,欢迎转载.但请注明出处:http://blog.csdn.net/jesson20121020 今天就来实现下查看图片及录音的功能,在编辑或者浏览记事时,点击图片.打开一个自己 ...