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. C语言编程基础

    主流C语言编译器介绍 关于GNU规范的语法扩展 用C语言构建一个可执行程序的流程 宏定义(无参宏定义和带参宏定义),C语言宏定义详解 条件编译,C语言条件编译详解 原码.反码.补码及位操作符,C语言位 ...

  2. select展开时 重新加载 option,ie 折叠问题 以及 chrome 没有变化问题

    这个bug是因为浏览器的渲染问题引起的 一:重新加载option的渲染处理 1:火狐能重新渲染,并且select不折叠 2:ie重新渲染,但是select收缩折叠 3:chrome直接不重新进行渲染, ...

  3. Python3用sys和time模块实现进度条

    import sys import time def view_bar(num, total): rate = float(num) / float(total) rate_num = int(rat ...

  4. js 简单数据类型和复杂数据类型的区别

    原始数据类型: number,string,boolean,undefined, null,object 基本类型(简单类型),值类型: number,string,boolean 复杂类型(引用类型 ...

  5. Qt 学习之路 2(41):model/view 架构

    Qt 学习之路 2(41):model/view 架构 豆子 2013年1月23日 Qt 学习之路 2 50条评论 有时,我们的系统需要显示大量数据,比如从数据库中读取数据,以自己的方式显示在自己的应 ...

  6. REST模式中HTTP请求方法(GET,POST,PUT,DELETE)

    一直在测试REST模式的WEB SERVICE接口,客户端的HTTP的请求方式一般分为四种:GET.POST.PUT.DELETE,这四种请求方式有什么不同呢.简单的说,GET就是获取资源,POST就 ...

  7. mac 配置charles

    从官网下载链接http://www.charlesproxy.com/download 附上注册码: Registered Name: https://zhile.io License Key: 48 ...

  8. python之文件读写(2)

    2. 写入数据到文件中 读取文件用read,那么写用什么嘞?用write!实际操作一下. 2.1 简单的写入数据到文件中 file = open("write_data", &qu ...

  9. LOJ6502. 「雅礼集训 2018 Day4」Divide(构造+dp)

    题目链接 https://loj.ac/problem/6502 题解 中间一档部分分提示我们将所有的 \(w_i\) 排序. 考虑如果我们能构造出这样一个 \(w_i\) 的序列,使得该序列满足:对 ...

  10. Luogu P1052 过河 DP

    复习复习DP...都忘了QAQ... 好了这道题我其实是看题解才会的... 方程 f[i]=min(f[i-j]+v[i]) v[i]表示i是不是石头 s<=j<=t 路径压缩引用一下证明 ...