《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)共享对象对象组合基础构建模块任务执行取消和关闭线程池的使用性能与可伸缩性并发程序的测试显示锁原子变量和非阻塞同步机制 一.线 ...
随机推荐
- [BZOJ 1855] 股票交易
Link: BZOJ 1855 传送门 Solution: 比较明显的$dp$模型 令$dp[i][j]$为第$i$天持有$j$支股票时的最大利润 对其购买股票和售出股票分别$dp$,这里以购买为例: ...
- BZOJ 2956 模积和(分块)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2956 [题目大意] 求∑∑((n%i)*(m%j))其中1<=i<=n,1 ...
- Codeforces 804E The same permutation(构造)
[题目链接] http://codeforces.com/contest/804/problem/E [题目大意] 给出一个1到n的排列,问每两个位置都进行一次交换最终排列不变是否可能, 如果可能输出 ...
- [CODECHEF]SEGPROD
题意:给定$a_{1\cdots n}$和$p$,多次询问$\prod\limits_{i=l}^ra_i$对$p$取模的值,强制在线,每次询问要求$O(1)$回答 一个微小的黑科技... 静态区间查 ...
- 升级到XCode6后,iOS8里设置tableview的setSeparatorInset:UIEdgeInsetsZero不起作用的解决办法
我们在使用tableview时会发现分割线的左边会短一些,通常可以使用 setSeparatorInset:UIEdgeInsetsZero 来解决.但是升级到XCode6之后,在iOS8里发现没有效 ...
- SpringBoot 整合 Jpa
项目目录结构 pom文件 <?xml version="1.0" encoding="UTF-8"?> <project xmlns=&quo ...
- HDU 4417 Super Mario(划分树)
Super Mario Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- 通过logstash收集mysql慢查询日志转换为json
input { file { type => "mysql-slow" path => "/var/log/slow_mysqld.log" sta ...
- 判断客户端是PC还是手持设备的JS代码【转】
1.第一种: 复制代码代码如下: function IsPC() { var userAgentInfo = navigator.userAgent; var Agents = [&quo ...
- delphi Align属性
---------------------------------------------- -