在进行锁处理的时候还有一个接口:Condition,这个接口可以由用户来自己进行锁的对象创建。

  Condition的作用是对锁进行更精确的控制。

  Conditionawait()方法相当于Objectwait()方法,Conditionsignal()方法相当于Objectnotify()方法,ConditionsignalAll()方法相当于ObjectnotifyAll()方法。

  不同的是Objectwait(), notify(), notifyAll() 方法是和“同步锁”(synchronized关键字)捆绑使用的;而Condition是需要与“互斥锁/共享锁”捆绑使用。

  Object Condition
休眠 wait() await()
唤醒单个线程 notify() signal()
唤醒多个线程 notifyAll() signalAll()

范例:观察Condition的基本使用

package so.strong.mall.concurrent;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class ConditionDemo {
private static String msg = null; //设置一个字符串
public static void main(String[] args) throws Exception{
final Lock myLock = new ReentrantLock(); //实例化Lock接口对象
final Condition condition = myLock.newCondition(); //创建一个新的Condition接口对象
myLock.lock();
//如果现在不进行锁定,那么Condition无法执行等代理处理机制,会出现IllegalMonitorStateException
try {
new Thread(new Runnable() {
@Override
public void run() {
myLock.lock();
try {
msg = "itermis.com";
condition.signal(); //唤醒等待的Condition
} finally {
myLock.unlock();
}
}
}).start();
condition.await(); //线程等待
System.out.println("*******主线程执行完毕,msg="+msg);
} finally {
myLock.unlock(); //解除阻塞状态
}
}
}
//*******主线程执行完毕,msg=itermis.com

  与之前的Object相比,唯一的区别在于:现在看不见明确的synchronized关键字,而取代synchronizedLock接口中的lock(),unlock()两个方法,而后在阻塞状态(同步状态)下可以使用Condition中的await()signal()方法进行等待与唤醒的操作处理。

范例:实现数据的缓冲控制

package so.strong.mall.concurrent;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; /**
* @author Termis
* @date 2018/5/3
*/
public class DataBufferDemo {
public static void main(String[] args) {
final DataBuffer db = new DataBuffer();
for (int i = 0; i < 3; i++) { //创建3个写线程
new Thread(new Runnable() {
@Override
public void run() {
for (int j = 0; j < 2; j++) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
db.put(Thread.currentThread().getName() + "写入数据,j=" + j);
}
}
}, "生产者-" + i).start();
} for (int i = 0; i < 5; i++) { //创建5个读线程
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
TimeUnit.SECONDS.sleep(3);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("[(" + Thread.currentThread().getName() + ")CONSUMER]" + db.get());
}
}
}, "消费者-" + i).start();
}
}
} class DataBuffer { //进行数据的缓冲操作控制
private static final int MAX_LENGTH = 5; // 该类之中保存的数组长度的个数为5
private Object[] data = new Object[MAX_LENGTH]; //定义一个数组进行全部数据的保存控制
private Lock myLock = new ReentrantLock(); //创建数据锁
private Condition putCondition = myLock.newCondition(); //数据保存的Condition控制
private Condition getCondition = myLock.newCondition(); //数据读取的Condition控制
private int putIndex = 0; //写入数据的索引
private int getIndex = 0; //读取数据的索引
private int count = 0; //当前保存的元素个数 public Object get() {
Object getObj = null;
this.myLock.lock();
try {
if (this.count == 0) //没有写入
this.getCondition.await(); //读取的线程要进行等待
getObj = this.data[this.getIndex++]; //读取指定索引数据
if (this.getIndex == MAX_LENGTH)
this.getIndex = 0; //重新开始读
this.count--; //因为读了一个数据之后,现在需要减少个数
this.putCondition.signal(); //告诉写线程可以写入
} catch (Exception e) {
e.printStackTrace();
} finally {
this.myLock.unlock();
}
return getObj;
} public void put(Object obj) { //进行缓冲数据的写入操作
this.myLock.lock(); //进入独占锁状态
try {
if (this.count == MAX_LENGTH) //保存的数据已经满了
this.putCondition.await(); //暂时先别进行数据保存了
this.data[this.putIndex++] = obj; //保存当前数据
if (this.putIndex == MAX_LENGTH) //现在索引已经写满
this.putIndex = 0; //重置数组操作的索引脚标
this.count++; //保存的个数需要做一个追加
this.getCondition.signal(); //唤醒消费线程
System.out.println("[(" + Thread.currentThread().getName() + ")写入缓冲-put()]" + obj);
} catch (Exception e) {
e.printStackTrace();
} finally {
this.myLock.unlock(); //不管如何最终一定要进行解锁
}
}
}
[(生产者-2)写入缓冲-put()]生产者-2写入数据,j=0
[(生产者-1)写入缓冲-put()]生产者-1写入数据,j=0
[(生产者-0)写入缓冲-put()]生产者-0写入数据,j=0
[(生产者-1)写入缓冲-put()]生产者-1写入数据,j=1
[(生产者-2)写入缓冲-put()]生产者-2写入数据,j=1
[(消费者-3)CONSUMER]生产者-2写入数据,j=0
[(消费者-4)CONSUMER]生产者-1写入数据,j=1
[(消费者-1)CONSUMER]生产者-0写入数据,j=0
[(消费者-2)CONSUMER]生产者-1写入数据,j=0
[(生产者-0)写入缓冲-put()]生产者-0写入数据,j=1
[(消费者-0)CONSUMER]生产者-2写入数据,j=1
[(消费者-3)CONSUMER]生产者-0写入数据,j=1

  对于生产者和消费者模型的实现,除了多线程基础实现之外,也可以采用以上的模式利用LockCondition进行精确控制。

JUC——线程同步锁(Condition精准控制)的更多相关文章

  1. JUC——线程同步锁(锁处理机制简介)

    锁处理机制简介 juc的开发框架解决的核心问题是并发访问和数据安全操作问题,当进行并发访问的时候如果对于锁的控制不当,就会造成死锁这样的阻塞问题. 为了解决这样的缺陷,juc里面重新针对于锁的概念进行 ...

  2. JUC——线程同步锁(ReentrantReadWriteLock读写锁)

    读写锁简介 所谓的读写锁值得是两把锁,在进行数据写入的时候有一个把“写锁”,而在进行数据读取的时候有一把“读锁”. 写锁会实现线程安全同步处理操作,而读锁可以被多个对象读取获取. 读写锁:ReadWr ...

  3. JUC——线程同步锁(LockSupport阻塞原语)

    java.util.concurrent.locks.LockSupport这个是一个独立的类,这个类的主要功能是用来解决Thread里面提供的suspend()(挂起线程).resume()(恢复运 ...

  4. JUC——线程同步锁(ReentrantLock)

    ReentrantLock简介 ReentrantLock是一个可重复的互斥锁,又被称为独占锁,可重入的意思是:ReentrantLock锁可以被单个线程多次获取.但是在同一个时间点只能被一个线程锁持 ...

  5. Python之路(第四十四篇)线程同步锁、死锁、递归锁、信号量

    在使用多线程的应用下,如何保证线程安全,以及线程之间的同步,或者访问共享变量等问题是十分棘手的问题,也是使用多线程下面临的问题,如果处理不好,会带来较严重的后果,使用python多线程中提供Lock ...

  6. 多线程 - 线程同步锁(lock、Monitor)

    1. 前言 多线程编程的时候,我们不光希望两个线程间能够实现逻辑上的先后顺序运行,还希望两个不相关的线程在访问同一个资源的时候,同时只能有一个线程对资源进行操作,否则就会出现无法预知的结果. 比如,有 ...

  7. Python并发编程-进程 线程 同步锁 线程死锁和递归锁

    进程是最小的资源单位,线程是最小的执行单位 一.进程 进程:就是一个程序在一个数据集上的一次动态执行过程. 进程由三部分组成: 1.程序:我们编写的程序用来描述进程要完成哪些功能以及如何完成 2.数据 ...

  8. Python3 进程 线程 同步锁 线程死锁和递归锁

    进程是最小的资源单位,线程是最小的执行单位 一.进程 进程:就是一个程序在一个数据集上的一次动态执行过程. 进程由三部分组成: 1.程序:我们编写的程序用来描述进程要完成哪些功能以及如何完成 2.数据 ...

  9. Java线程同步锁

    把synchronized当作函数修饰符时,示例代码如下: Public synchronized void method(){ //-. } 这也就是同步方法,那这时synchronized锁定的是 ...

随机推荐

  1. return 返回值的问题

    def yue(): print("1. 打开手机") print("2. 打开陌陌") print("3. 找个漂亮的小姐姐") prin ...

  2. 第一篇,编译生成libcef_dll_wrapper

    因为工作原因需要在程序里面嵌入地图,在网上看了百度地图和高德地图都没有提供c++的接口,提供有web接口,那只好在程序里面嵌入web控件了,第一想到的是web browser控件,接着脑海里又想到IE ...

  3. RYU基础整理

    1. RYU结构,源码 1.1 RYU文件目录 下面介绍ryu/ryu目录下的主要目录内容. base base中有一个非常重要的文件:app_manager.py,其作用是RYU应用的管理中心.用于 ...

  4. MySQL知识总结(三)存储过程

    1. 创建存储过程 1.1 无参数存储过程 CREATE PROCEDURE bruce_procedure () BEGIN --1.声明变量 --2.执行业务逻辑 END 1.2 有参数的存储过程 ...

  5. 【linux】安装和配置 mysql服务器

    按照官网教程,根据自己的系统安装不同的发行版 https://dev.mysql.com/doc/refman/5.6/en/linux-installation-yum-repo.html 配置: ...

  6. Python之美[从菜鸟到高手]--2+2=5

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/yueguanghaidao/article/details/35644165     今天在伯乐在线 ...

  7. virtualbox+vagrant学习-2(command cli)-17-vagrant ssh命令

    SSH 格式: vagrant ssh [options] [name|id] [-- extra ssh args] 这将SSH导入正在运行的vagrant机器,并允许你访问机器的shell. us ...

  8. memcached/memcache安装

    memcached安装 查找memcached:        yum  search  memcached安装 memcached             yum  -y install memca ...

  9. maven3 下载列表

    https://archive.apache.org/dist/maven/maven-3/ Parent Directory - 3.0.4/ 2012-09-11 09:37 - 3.0.5/ 2 ...

  10. python redis 的基本操作指令

    #!/usr/bin/env python # -*- coding: utf-8 -*- ''' redis基本命令和基本用法详解 1.redis连接 2.redis连接池 3.redis基本命令 ...