通过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对象实现多线程同步的更多相关文章

  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. (转)Unity3D 开发优秀技术资源汇总

    原文:http://www.j2megame.com/html/xwzx/ty/3179.html Unity3D 博客 http://www.dapp.com.br/  by Dapp http:/ ...

  2. python的序列化

    参考:https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/0013868322157 ...

  3. 让用VS2012/VS2013编写的程序在XP中顺利执行

    微软为了推销自家平台,默认配置下VS2012和VS2013编写的应用程序仅仅能在Vista/Win7/Win8上执行.但幸好还保留了生成XP程序的设置项.XP和Win2003的用户还是大量存在的,我们 ...

  4. 使apache的日志文件里不记录图片文件

    找到: LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-A ...

  5. Geek改变世界

    在10月24号的GeekPwn到来前,主办方 — 来自Keen Team的创始人大牛蛙希望我能为GeekPwn写点东西.作为GeekPwn的顾问,我也非常乐意为这次首秀做一点事情. 正如之前提到过的, ...

  6. Python中将打印输出日志文件

    一. 利用sys.stdout将print行导向到你定义的日志文件中,例如: import sys # make a copy of original stdout route stdout_back ...

  7. 如何设计好的RESTful API 之好的RESTful API 特征

    原文地址:http://blog.csdn.net/ywk253100/article/details/25654021 导读:设计好RESTful API对于软件架构的可扩展性.可伸缩性和消费者的体 ...

  8. 创建es索引{"acknowledged"=>true, "shards_acknowledged"=>false}

    创建es索引{"acknowledged"=>true, "shards_acknowledged"=>false} [2018-05-19T13: ...

  9. PS如何使用制作图片投影效果

    如果仅仅是同样大小的背景(灰色或者黑色),则只要新建一个和比原图大三个像素的文件(比如这里原图片为100×100,我就建立一个103×103的文件)把图片放在左上角,剩下的部分填充灰色或者黑色.然而这 ...

  10. react-native-router-flux 页面跳转与传值

    1.正向跳转假设情景:从Home页跳转到Profile页面,Profile场景的key值为profile 不带参数: Actions.profile 带参数: Actions.profile({'ke ...