为什么 java wait/notify 必须与 synchronized 一起使用,jvm究竟做了些什么
2024-10-20 20:59:18
这个课题提出来的是原先的线程并发解决的思路。目前解决线程并发,可以是lock接口结合condition 并发问题一直以来就是线程必不可少的话题。
java 是第一个内置对多线程支持的主流编程语言。在Java5之前,对多线程的支持主要是通过对块结构的同步实现的(synchronized配合wait,notify,notifyAll),Java5引入了java.util.concurrent包,提供了对多线程编程的更高层的支持。
今天我们来说说。java中,线程提供我们解决并发。同步的方法
通常可以使用synchronized和notify,notifyAll以及wait方法来实现线程之间的数据传递及控制。对于对象obj来说:
- obj.wait():该方法的调用,使得调用该方法的执行线程(T1)放弃obj的对象锁并阻塞,直到别的线程调用了obj的notifyAll方法、或者别的线程调用了obj的notify方法且JVM选择唤醒(T1),被唤醒的线程(T1)依旧阻塞在wait方法中,与其它的线程一起争夺obj的对象锁,直到它再次获得了obj的对象锁之后,才能从wait方法中返回。(除了notify方法,wait还有带有时间参数的版本,在等待了超过所设时间之后,T1线程一样会被唤醒,进入到争夺obj对象锁的行列;另外中断可以直接跳出wait方法)
- obj.notify():该方法的调用,会从所有正在等待obj对象锁的线程中,唤醒其中的一个(选择算法依赖于不同实现),被唤醒的线程此时加入到了obj对象锁的争夺之中,然而该notify方法的执行线程此时并未释放obj的对象锁,而是离开synchronized代码块时释放。因此在notify方法之后,synchronized代码块结束之前,所有其他被唤醒的,等待obj对象锁的线程依旧被阻塞。
- obj.notifyAll():与notify的区别是,该方法会唤醒所有正在等待obj对象锁的线程。(不过同一时刻,也只有一个线程可以拥有obj的对象锁)
要注意的是,wai,notify以及notifyAll方法的调用必须在相应的synchronized代码块之中
线程就是程序执行的路径。多线程,也就不难理解了,程序执行的多条路径,它们独立执行,但是又有莫大的联系
wait/notify字面意思是等待和告知
package com.huojg.test; public class ThreadA {
public static void main(String[] args) {
ThreadB b = new ThreadB();
b.start();// 主线程中启动另外一个线程
System.out.println("b is start....");
// 括号里的b是什么意思,应该很好理解吧
synchronized (b) {
try {
System.out.println("Waiting for b to complete...");
b.wait();// 这一句是什么意思,究竟谁等待?
System.out.println("ThreadB is Completed. Now back to main thread");
} catch (InterruptedException e) {
} }
System.out.println("Total is :" + b.total);
}
} class ThreadB extends Thread {
int total; public void run() {
synchronized (this) {
System.out.println("ThreadB is running..");
for (int i = 0; i <= 100; i++) {
total += i;
}
System.out.println("total is" + total);
notify();
}
}
}
b is start....
ThreadB is running..
total is5050
Waiting for b to complete...
ThreadB is Completed. Now back to main thread
Total is :5050
从程序运行的结果来看就不难理解wait/notify了,wait是让使用wait方法的对象等待,暂时先把对象锁给让出来,给其它持有该锁的对象用,其它对象用完后再告知(notify)等待的那个对象可以继续执行了,整个过程就是这样。wait/notify主要用于一个线程要等待另一个线程执行完后,然后得到执行结果的情况。
最新文章
- React单元测试——十八般兵器齐上阵,环境构建篇
- rsync+inotify实现远程数据备份
- IOS 手势-轻点、触摸、手势、事件
- jquery/js特效代码总结(一):tab切换
- 经典71道Android试题及答案
- Android 如何全局获取Context
- 01_SpringMVC流程架构图
- JavaScript高级程序设计28.pdf
- git新手碰到的各种奇葩问题之一
- SpringMvc学习-增删改查
- cubieboard 配置WIFI
- for 循环 和 Array 数组对象
- linux curl 命令的使用
- Todolist功能开发
- SQLServer&#160;学习笔记之超详细基础SQL语句&#160;Part&#160;11
- 从最简单的实例学习ARM 指令集(三)
- 20155229付钰涵-虚拟机安装及LINUX命令学习
- 如何在VScode中添加代码片段
- 理想中的 PCB 文件格式
- linux下安装配置apache+nagios
热门文章
- Jenkins忘记密码的修复方法(Windows/Linux)
- 转:[Asp.net]常见数据导入Excel,Excel数据导入数据库解决方案,总有一款适合你!
- html 基础二
- 【log4j】springboot项目启动 ,使用的druid数据源,log4j报错 log4j:WARN Please initialize the log4j system properly.
- numpy中结构数组
- UVa116 (单向TSP,多决策问题)
- 分享三个USB抓包软件---Bus Hound,USBlyzer 和-USBTrace
- Lock flag DX
- Webpack打包工具学习使用
- 【Android高级】NDK/JNI编程技术基础介绍