看这本书之前,对wait和notify认识大概就是,调用wait的线程A堵塞之后,一旦另外有线程调用notify方法。线程A会立马从wait方法处返回。看完这本书后。发现自己的认识实在太肤浅了。。。。。

线程调用wait()后,会释放已经获得的锁。

同一时候进入Waiting状态,而非Blocked状态。唯独等待其它的线程调用notify()方法且释放锁之后。当前线程才会从wait()方法处返回。只发出通知是不够用的。还须要发出通知的线程释放锁。

然而notify()方法的调用并不意味着锁的释放。

贴出原书的demo,稍作了些改动。

/**
*
*/
package chapter04; import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit; /**
* 6-11
*/
public class WaitNotify {
private static final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
static boolean flag = true;
static Object lock = new Object(); public static void main(String[] args) {
Thread waitThread = new Thread(new Wait(), "WaitThread");
waitThread.start();
sleepSeconds(1); Thread notifyThread = new Thread(new Notify(), "NotifyThread");
notifyThread.start();
} static class Wait implements Runnable {
public void run() {
synchronized (lock) {
// 当条件不满足时,继续wait,同一时候释放了lock的锁
while (flag) {
try {
System.out.println(CuttentThreadName() + " flag is true. wait @ " + sdf.format(new Date()));
lock.wait();
System.out.println(CuttentThreadName() + " gained lock again. wait @ " + sdf.format(new Date()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 条件满足时。完毕工作
System.out.println(CuttentThreadName() + " flag is false. running @ " + sdf.format(new Date()));
}
}
} private static String CuttentThreadName() {
return Thread.currentThread().getName();
} static class Notify implements Runnable {
@Override
public void run() {
// 加锁,拥有lock的Monitor
synchronized (lock) {
// 获取lock的锁。然后进行通知,通知时不会释放lock的锁,
// 直到当前线程释放了lock后,WaitThread才干从wait方法中返回
System.out.println(CuttentThreadName() + " hold lock. notify @ " + sdf.format(new Date()));
lock.notifyAll();
flag = false;
sleepSeconds(5);
System.out.println(CuttentThreadName() + " is releasing lock @ " + sdf.format(new Date()));
}
// 再次加锁
synchronized (lock) {
System.out.println(CuttentThreadName() + " hold lock again. sleep @ " + sdf.format(new Date()));
sleepSeconds(5);
System.out.println(CuttentThreadName() + " is releasing lock @ " + sdf.format(new Date()));
}
}
} private static void sleepSeconds(int timeout) {
try {
TimeUnit.SECONDS.sleep(timeout);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

输出结果为:

WaitThread flag is true. wait @ 20:58:32
NotifyThread hold lock. notify @ 20:58:33
NotifyThread is releasing lock @ 20:58:38
NotifyThread hold lock again. sleep @ 20:58:38
NotifyThread is releasing lock @ 20:58:43
WaitThread gained lock again. wait @ 20:58:43
WaitThread flag is false. running @ 20:58:43

通过输出结果,我们能够发现几个问题。

1.NotifyThread调用notifyAll()方法后,WaitThread并没有立马从wait()方法处返回。

由于这个时候NotifyThread并没有释放锁。

2.程序61行,NotifyThread第一次释放锁,然而WaitThread不争气,并没有抢到这把锁。依然处于Blocked状态。

3.直到67行。NotifyThread再一次释放锁。WaitThread获得了锁,这才从wait()处返回继续运行。

4.线程从wait()方法返回的前提是,获得synchronized须要的锁。

分析完原书的demo之后,是否有跟我一样的感觉,以前的认识是那么的too young too simple。

《Java并发编程的艺术》读书笔记:等待/通知机制的更多相关文章

  1. Java并发编程的艺术读书笔记(2)-并发编程模型

    title: Java并发编程的艺术读书笔记(2)-并发编程模型 date: 2017-05-05 23:37:20 tags: ['多线程','并发'] categories: 读书笔记 --- 1 ...

  2. Java并发编程的艺术读书笔记(1)-并发编程的挑战

    title: Java并发编程的艺术读书笔记(1)-并发编程的挑战 date: 2017-05-03 23:28:45 tags: ['多线程','并发'] categories: 读书笔记 --- ...

  3. java并发编程实战《六》等待-通知机制

    用"等待-通知"机制优化循环等待 前言 在破坏占用且等待条件的时候,如果转出账本和转入账本不满足同时在文件架上这个条件,就用死循环的方式来循环等待. 1 // 一次性申请转出账户和 ...

  4. synchronized的实现原理-java并发编程的艺术读书笔记

    1.synchronized实现同步的基础 Java中的每个对象都是可以作为锁,具体有3种表现. 1.对于普通同步方法,锁是当前实例对象. 2.对于静态同步方法,锁是当前类的Class对象. 3.对于 ...

  5. 《Java并发编程实战》读书笔记一 -- 简介

    <Java并发编程实战>读书笔记一 -- 简介 并发的历史 并发的历史,也是人类利用有限的资源去提高生产效率的一个的例子. 设想现在有台计算机,这台计算机具有以下的资源: 单核CPU一个 ...

  6. 《Java并发编程的艺术》笔记

    第1章 并发编程的挑战 1.1 上下文切换 CPU通过时间片分配算法来循环执行任务,任务从保存到再加载的过程就是一次上下文切换. 减少上下文切换的方法有4种:无锁并发编程.CAS算法.使用最少线程.使 ...

  7. 《java并发编程实战》读书笔记2--对象的共享,可见性,安全发布,线程封闭,不变性

    这章的主要内容是:如何共享和发布对象,从而使它们能够安全地由多个线程同时访问. 内存的可见性 确保当一个线程修改了对象状态后,其他线程能够看到发生的状态变化. 上面的程序中NoVisibility可能 ...

  8. 《java多线程编程核心技术》不使用等待通知机制 实现线程间通信的 疑问分析

    不使用等待通知机制 实现线程间通信的 疑问分析 2018年04月03日 17:15:08       ayf 阅读数:33 编辑 <java多线程编程核心技术>一书第三章开头,有如下案例: ...

  9. 《java并发编程实战》读书笔记4--基础构建模块,java中的同步容器类&并发容器类&同步工具类,消费者模式

    上一章说道委托是创建线程安全类的一个最有效策略,只需让现有的线程安全的类管理所有的状态即可.那么这章便说的是怎么利用java平台类库的并发基础构建模块呢? 5.1 同步容器类 包括Vector和Has ...

  10. 《Java并发编程实战》读书笔记

    Subsections 线程安全(Thread safety)锁(lock)共享对象对象组合基础构建模块任务执行取消和关闭线程池的使用性能与可伸缩性并发程序的测试显示锁原子变量和非阻塞同步机制 一.线 ...

随机推荐

  1. 第8天-setInterval/setTimeout

    setInterval是什么? setInterval()方法重复调用一个函数或执行一个代码段,在每次调用之间具有固定的时间延迟. setInterval(函数,间隔时间) 例如 function f ...

  2. Meeting Rooms II -- LeetCode

    Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...] (si ...

  3. JZYZOJ1369 [coci2012]覆盖字符串 AC自动机

    http://172.20.6.3/Problem_Show.asp?id=1369 trie树如果不优化就这么往里面放这么多单词肯定超空间+超时,所以需要去掉无用的字符串(不属于原字符串的),但是一 ...

  4. POJ 3378 Crazy Thairs(树状数组+DP)

    [题目链接] http://poj.org/problem?id=3378 [题目大意] 给出一个序列,求序列中长度等于5的LIS数量. [题解] 我们发现对于每个数长度为k的LIS有dp[k][i] ...

  5. Codeforces 724E Goods transportation(最小割转DP)

    [题目链接] http://codeforces.com/problemset/problem/724/E [题目大意] 每个城市有pi的物品可以运出去卖,si个物品可以买, 编号小的城市可以往编号大 ...

  6. 用Java Swing实现Freecell(空当接龙)

     目录 引言 1 游戏规则 2 界面设计和大致逻辑 2.1 界面设计 2.2 大致逻辑 3 主要功能模块设计与实现 3.1 主要思路 3.2 主要工具类 3.3 异常类 3.4 游戏初始化模块 3.5 ...

  7. win7 64位 php环境开启curl服务Call to undefined function

    无法使用curl_init(),一般情况问题可能出在没有去加载php的扩展文件php_curl.dll(windows操作系统),但是检查了一下系统配置,发现,环境下已经将php.ini文件里 ;ex ...

  8. ASP.NET Core管道深度剖析

    ASP.NET管道 以IIS 6.0为例,在工作进程w3wp.exe中,利用Aspnet_ispai.dll加载.NET运行时(如果.NET运行时尚未加载).IIS 6引入了应用程序池的概念,一个工作 ...

  9. android基础知识复习——RelativeLayout布局属性、背景、半透明设置(XML设置)

    转自:http://blog.csdn.net/fansongy/article/details/6817968 复习布局与XML,写了一个空的登录界面.XML的注释我写在当行的后面了.程序运行图: ...

  10. 8.8.8.8和8.8.4.4 DNS域名解析服务器

    而Google表示推出免费DNS服务的主要目的就是为了改进网络浏览速度.改善网络用户的浏览体验,为此Google自行开发的软件对DNS服务器技术进行了改进,通过采用预获取技术提升性能,同时保证了DNS ...