通过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 线程安全:当多个线程访问某一个类(对象或方法)时,这个类始终都能表现出正确的行为,那么这个类(对象或方法) ...
随机推荐
- bean装配--auto
1,Dao package com.songyan.autoZhuangpei; public interface UserDao { public void say(); } package com ...
- MySQL命令show full processlist
processlist命令的输出结果显示了有哪些线程在运行,可以检查当前数据库的运行状态,两种方式使用这个命令. 1 进入MySQL/bin目录下输入mysqladmin processlist; 2 ...
- sharepoint2010无法连接到配置数据库。
最近VS部署又遇到这个问题了,记录一下. 然后以管理员省份打开sharePoint管理中心,发现页面展示光秃秃的“无法连接到配置数据库” 解决方式:问的同事. 找到计算机 服务 项, 这个启动下 这个 ...
- appium 测试模拟器时输入adb devices显示 unauthorized
https://stackoverflow.com/questions/32132434/set-adb-vendor-keys 也就是点击AVD管理器右边的下拉列表,点击清除数据,再重启虚拟机 0d ...
- Unix网络编程学习笔记之第12章 IPv4与IPv6的互操作性
一. 简单介绍 如果我们本章讨论的主机都是支持双栈的,即支持IPv4地址.也支持Ipv6地址. 我们本次讨论的点:client与server端使用的是不同类型的地址.由于同样类型的地址没什么可讲的. ...
- hive删除表报错
metastore.RetryingHMSHandler: HMSHandler Fatal error: javax.jdo.JDODataStoreException: You have an e ...
- 2017.6.27 jdbc基本使用
参考来自:http://www.runoob.com/w3cnote/jdbc-use-guide.html 1.jdbc的执行流程 JDBC API 允许用户访问任何形式的表格数据,尤其是存储在关系 ...
- 转:敏捷方式scrum 方案
http://www.cnblogs.com/taven/archive/2010/10/17/1853386.html 现在敏捷开发是越来越火了,人人都在谈敏捷,人人都在学习Scrum和XP... ...
- Java过滤器(Filter)与SpringMVC拦截器(Interceptor)之间的关系与区别
过滤器和拦截器的区别: ①拦截器是基于java的反射机制的,而过滤器是基于函数回调. ②拦截器不依赖与servlet容器,过滤器依赖与servlet容器. ③拦截器只能对action请求起作用,而过滤 ...
- python项目导出所需要的依赖库
使用pip freeze $ pip freeze > requirements.txt 这种方式是把整个环境中的包都列出来了,如果是虚拟环境可以使用. 通常情况下我们只需要导出当前项目的req ...