《Java并发编程的艺术》读书笔记:等待/通知机制
看这本书之前,对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并发编程的艺术》读书笔记:等待/通知机制的更多相关文章
- Java并发编程的艺术读书笔记(2)-并发编程模型
title: Java并发编程的艺术读书笔记(2)-并发编程模型 date: 2017-05-05 23:37:20 tags: ['多线程','并发'] categories: 读书笔记 --- 1 ...
- Java并发编程的艺术读书笔记(1)-并发编程的挑战
title: Java并发编程的艺术读书笔记(1)-并发编程的挑战 date: 2017-05-03 23:28:45 tags: ['多线程','并发'] categories: 读书笔记 --- ...
- java并发编程实战《六》等待-通知机制
用"等待-通知"机制优化循环等待 前言 在破坏占用且等待条件的时候,如果转出账本和转入账本不满足同时在文件架上这个条件,就用死循环的方式来循环等待. 1 // 一次性申请转出账户和 ...
- synchronized的实现原理-java并发编程的艺术读书笔记
1.synchronized实现同步的基础 Java中的每个对象都是可以作为锁,具体有3种表现. 1.对于普通同步方法,锁是当前实例对象. 2.对于静态同步方法,锁是当前类的Class对象. 3.对于 ...
- 《Java并发编程实战》读书笔记一 -- 简介
<Java并发编程实战>读书笔记一 -- 简介 并发的历史 并发的历史,也是人类利用有限的资源去提高生产效率的一个的例子. 设想现在有台计算机,这台计算机具有以下的资源: 单核CPU一个 ...
- 《Java并发编程的艺术》笔记
第1章 并发编程的挑战 1.1 上下文切换 CPU通过时间片分配算法来循环执行任务,任务从保存到再加载的过程就是一次上下文切换. 减少上下文切换的方法有4种:无锁并发编程.CAS算法.使用最少线程.使 ...
- 《java并发编程实战》读书笔记2--对象的共享,可见性,安全发布,线程封闭,不变性
这章的主要内容是:如何共享和发布对象,从而使它们能够安全地由多个线程同时访问. 内存的可见性 确保当一个线程修改了对象状态后,其他线程能够看到发生的状态变化. 上面的程序中NoVisibility可能 ...
- 《java多线程编程核心技术》不使用等待通知机制 实现线程间通信的 疑问分析
不使用等待通知机制 实现线程间通信的 疑问分析 2018年04月03日 17:15:08 ayf 阅读数:33 编辑 <java多线程编程核心技术>一书第三章开头,有如下案例: ...
- 《java并发编程实战》读书笔记4--基础构建模块,java中的同步容器类&并发容器类&同步工具类,消费者模式
上一章说道委托是创建线程安全类的一个最有效策略,只需让现有的线程安全的类管理所有的状态即可.那么这章便说的是怎么利用java平台类库的并发基础构建模块呢? 5.1 同步容器类 包括Vector和Has ...
- 《Java并发编程实战》读书笔记
Subsections 线程安全(Thread safety)锁(lock)共享对象对象组合基础构建模块任务执行取消和关闭线程池的使用性能与可伸缩性并发程序的测试显示锁原子变量和非阻塞同步机制 一.线 ...
随机推荐
- HDU 6373 Pinball
Pinball Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total S ...
- 输入输出格式之Python版
# 有多组输入数据,但没有具体的告诉你有多少组,只是让你对应每组输入,应该怎样输出. while True: try: a, b = map(int, raw_input().strip().spli ...
- 【BFS】Tester Program
[poj1024]Tester Program Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 2760 Accepted ...
- 【二分】【线段树】hdu6070 Dirt Ratio
size(l,r)表示区间l,r权值的种类数,让你求min{size(l,r)/(r-l+1)}(1<=l<=r<=n). last[r]表示a[r]上一次出现的位置, 就是二分验证 ...
- error C2248: 'MyString::pCharArray' : cannot access private member declared in class 'MyString'
std::ostream & operator<<(std::ostream os,const MyString & mystr){os<<mystr.pCha ...
- ConCurrent并发包 - Lock详解(转)
synchronized的缺陷 我们知道,可以利用synchronized关键字来实现共享资源的互斥访问.Java 5在java.util.concurrent.locks包下提供了另一种来实现线 ...
- 使用moment.js管理时间
如果在nodejs下 npm install moment 引用模块: var moment = require('moment'); 用法: 当前时间:2015-11-07 18:00:51 mom ...
- openGl 基础
最近由于手机项目中需要用到OpenGL ES的知识,所以这段时间正在研究OpenGL的相关知识.因为OpenGL ES是OpenGL的剪裁版本,所以我直接从OpenGL入手,然后再去看OpenGL E ...
- Nokitjs 系列-01 - HelloWorld
一.前言 本篇文章需要读者有一点 Node.js 基础的了解,并且已经安装了 Node.js (node.npm),但并不需要有 Nokit 的知识,本文将简单介绍 Nokitjs 的安装使用,并编写 ...
- SQL locate()函数
LOCATE(substr,str), LOCATE(substr,str,pos) 第一个语法返回字符串str第一次出现的子串substr的位置. 第二个语法返回第一次出现在字符串str的子串sub ...