sychronized、wait、notify、notifyAll、sleep

在多线程环境下,为了防止多个线程同时调用同一个方法、修改同一份变量,造成数据读取结果混乱,可以使用synchronized关键字,对一个方法或者代码块实现同步调用,即只能一个线程调用完此方法后,下一个线程才能调用此方法。

当synchronized修饰的是一个类方法时,使用的是此类的Monitor实现同步(锁)。

当synchronized修饰的是一个实例方法时,使用的是此实例的Monitor实现同步(锁)。

当synchronized修饰的是一个代码块时,使用的是括号中变量的Monitor实现同步(锁)。

在StringBuffer、Hashtable、Vector等类中,为了实现方法同步,大量使用了sychronized关键字修饰方法。

当sychronized修饰的方法或者代码块,执行sleep时,进入time_waiting阶段,并会继续持有锁,直到sleep结束,或者被interrupted,继续执行,直到释放锁。

当sychronized修饰的方法或者代码块,执行wait时,进入waiting阶段,并释放持有的锁,当收到notify通知,或者被interrupted后,会重新竞争获取到锁,才会继续运行。注意,此时虽然处于同步方法中,但其在wait时锁被释放了,只有重新竞争获得锁,才能继续运行。

在sychronized修饰的方法或者代码块中,如果执行notify,会唤醒一个waiting(同一个对象锁)中的线程进入runnable阶段,等到退出sychronized区域,waiting的线程获得锁继续执行进入running阶段;如果执行notifyAll方法,会唤醒所有waiting(同一个对象锁)中的线程,等到当前线程退出sychronized区域,所有waiting的线程竞争锁,未竞争获得锁的线程再次进入waiting阶段,等待唤醒。

ReentrantLock、Condition

使用ReentrantLock类实例化一个lock实例,并可以通过lock实例新建一个Condition实例。

使用时,先用lock实例的lock方法,获得锁,在获得锁的期间可以使用此lock的Condition实例,进行await、signal、singalAll方法,发送信号,进行线程间通信。

举一个阻塞队列的例子:

通过lock对象,新建了两个Condition:notEmpty、notFull。

执行add操作时,会检查list的元素个数是否达到最大值,达到时,等待notFull信号。

执行take操作时,会检查list的元素个数是否为0,为0时,等待notEmpty信号。

add执行成功时,会发送notEmpty信号,通知执行take的线程,等到add操作的lock执行unlock后,去获取数据。

take执行成功时,会发送notFull信号,通知执行add的线程,等到take操作的lock执行unlock后,在去添加数据。

注意:在Conditon发送各种信号之前,创建他们的lock必须执行lock()操作,获取锁;在Conditon发送各种信号之后,创建他们的lock必须执行unlock()操作,释放锁。

class MyQueue {
private ReentrantLock lock = new ReentrantLock();
private Condition notEmpty = lock.newCondition();
private Condition notFull = lock.newCondition();
private AtomicInteger count = new AtomicInteger(0);
private List<String> list = new LinkedList<String>();
private final int MaxCount = 10; public void add(String str) {
lock.lock();
try {
while (count.get() > MaxCount) {
notFull.await();
}
list.add(str);
count.incrementAndGet();
notEmpty.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} public String take() {
String retStr = null;
lock.lock();
try {
while (count.get() == 0) {
notEmpty.await();
}
retStr = list.remove(0);
count.decrementAndGet();
notFull.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
return retStr;
}
}

java ReentrantLock Condition的更多相关文章

  1. java并发编程——通过ReentrantLock,Condition实现银行存取款

         java.util.concurrent.locks包为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器.该框架允许更灵活地使用锁和条件,但以更难用的语法为代价. Lock 接口 ...

  2. java 多线程 Thread 锁ReentrantLock;Condition等待与通知;公平锁

    1,介绍: import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock;   在JA ...

  3. java ReentrantLock结合条件队列 实现生产者-消费者模式 以及ReentratLock和Synchronized对比

    package reentrantlock; import java.util.ArrayList; public class ProviderAndConsumerTest { static Pro ...

  4. 在Java的Condition接口【唤醒全部线程】

    在Java的Condition接口中,存在的几个方法跟Synchronized中的wait(),waitall(),wait(time ^),这个几个方法一一对应起来,但是在Lock.newCondi ...

  5. java ReentrantLock可重入锁功能

    1.可重入锁是可以中断的,如果发生了死锁,可以中断程序 //如下程序出现死锁,不去kill jvm无法解决死锁 public class Uninterruptible { public static ...

  6. java多线程-Condition

    Condition 将 Object 监视器方法(wait.notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set ...

  7. Java并发控制:ReentrantLock Condition使用详解

    生产者-消费者(producer-consumer)问题,也称作有界缓冲区(bounded-buffer)问题,两个进程共享一个公共的固定大小的缓冲区.其中一个是生产者,用于将消息放入缓冲区:另外一个 ...

  8. java线程并发控制:ReentrantLock Condition使用详解

    本文摘自:http://outofmemory.cn/java/java.util.concurrent/lock-reentrantlock-condition java的java.util.con ...

  9. Java ReEntrantLock 之 Condition条件(Java代码实战-002)

    import java.util.LinkedList; import java.util.concurrent.locks.Condition; import java.util.concurren ...

随机推荐

  1. NSCalendar日历

    前言 NSCalendar 对世界上现存的常用的历法进行了封装,既提供了不同历法的时间信息,又支持日历的计算. NSCalendar -- 日历类,它提供了大部分的日期计算接口,并且允许您在NSDat ...

  2. poi将图片导入excel(Java代码)

    package com.fh.util;import java.awt.image.BufferedImage;  import java.io.ByteArrayOutputStream;  imp ...

  3. leecode刷题(2)-- 买卖股票的最佳时机

    买卖股票的最佳时机 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. 设计一个算法来计算你所能获取的最大利润.你可以尽可能地完成更多的交易(多次买卖一支股票). 注意:你不能同时参与多 ...

  4. bit、Byte、bps、Bps、pps、Gbps的单位的说明及换算

    一.bit与Byte区别 1. bit(比特) 是电脑记忆体的最小单元,在二进制计算机中,每一比特代表0或1的数位信号. 2. Byte(单位字节) 一般表示存储介质大小的单位,数字.字母和特殊符号占 ...

  5. 选择排序 思想 JAVA实现

    已知一个数组 9.29.95.47.79.37.18.56.96.22 使用选择排序是数组有序 选择排序同样是一个运行时间为O(N²)的排序算法. 算法思想:(以从小到大为例) 9.29.95.47. ...

  6. Unity3d 中 将远程 MySQL 数据库转换为本地 Sqlite

    1.创建MySQL2Sqlite脚本mysql2sqlite.sh:(代码地址:https://gist.github.com/esperlu/943776) #!/bin/sh # Converts ...

  7. 神奇的Form表单

    今天坐标单上传,提交的按钮使用了<button>,发现不论怎么写ajax和设置form表单,都会刷新页面,百思不得解,然后偶然间把<button>变成<input typ ...

  8. 01、前端需要注意哪些SEO?

    1.前端需要注意哪些SEO? 1)设置网站TDK标签的设置 2)图片img标签必须加上alt属性 3)h1~h6标签合理使用 4)a标签增加rel="nofollow" 5) 安装 ...

  9. clustalX2使用以及相关的问题

    Clustalx的操作 第一步:输入序列文件. 第二步:设定比对的一些参数. 参数设定窗口. 第三步:开始序列比对. 第四步:比对完成,选择保存结果文件的格式 相关问题 CLUSTALX-是CLUST ...

  10. 小a的计算器

    链接:https://ac.nowcoder.com/acm/contest/317/A来源:牛客网 小a的数学基础实在太差了,以至于他只会用计算器算数.他的计算器比较特殊,只有+,−,×,/+,−, ...