关于join() 是否会释放锁的一些思考
# 首先从一个很有意思的问题开始:
- 问 : Thread 的join() 方法是否会释放锁?
- 答: 会!
# 如果一切到这里就结束了,那可能也就没有这篇小记了,但是我的脑子却冒出了一些奇怪的想法:
- 释放哪个对象的锁呢?
- 难道是释放父线程所持有的所有对象的锁?
-- 其实如果看了源码,很容易明白释放的是运行(这个地方可能有些歧义,但是我也不知道怎么说最好)join()方法的那个线程对象的锁,不过这些都是后话,我们且往下看;
# 然后我就写了代码来验证一下我的猜想, 代码如下:
public class QQ {
public static void main(String[] args) {
Object oo = new Object();
Thread thread1 = new MyThread("thread1 -- ", oo);
thread1.start();
synchronized (oo) {
for (int i = 0; i < 100; i++) {
if (i == 20) {
try {
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " -- " + i);
}
}
}
}
class MyThread extends Thread {
private String name;
private Object oo;
public MyThread(String name, Object oo) {
this.name = name;
this.oo = oo;
}
@Override
public void run() {
synchronized (oo) {
for (int i = 0; i < 100; i++) {
System.out.println(name + i);
}
}
}
}
- 运行一下,输出到 main -- 19 的时候,卡住了。
- 接下来我们来寻找卡住的原因;
-- 先使用jps找到出问题程序的进程号
-- jstack pid 来查看线程堆栈,结果如下图
"Thread-1" #14 prio=5 os_prio=0 tid=0x0000000018fa9000 nid=0x3f80 waiting for monitor entry [0x0000000019b0f000]
java.lang.Thread.State: BLOCKED (on object monitor)
- waiting to lock <0x00000000d8a06298> (a java.lang.Object) "main" #1 prio=5 os_prio=0 tid=0x000000000228e800 nid=0x3d6c in Object.wait() [0x00000000028af000]
java.lang.Thread.State: WAITING (on object monitor)
- locked <0x00000000d8a06298> (a java.lang.Object)
-- 上图中我删掉了很多东西,只留下了一些关键的部分;首先我们看到 Thread-1 和 main 都在 waiting 状态,然后再注意到 Thread-1 在等待锁 <0x00000000d8a06298>,
但是main持有锁<0x00000000d8a06298>, 这又是什么情况呢? 难道 main 没有释放锁?
- 这时候我们就回到了最初的问题,到底join()的时候释放的是谁的锁,通过查看join()方法的源码,很容易看到,其实调用的是 this.wait(),也就是说释放的是Thread-1 这个对象的锁
# 接着我们来用下面的代码证实一下我们得出的结论
public class QQ {
public static void main(String[] args) {
Object oo = new Object();
Thread thread1 = new MyThread("thread1 -- ", oo);
thread1.start();
synchronized (thread1) {
for (int i = 0; i < 100; i++) {
if (i == 20) {
try {
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " -- " + i);
}
}
}
}
class MyThread extends Thread {
private String name;
private Object oo;
public MyThread(String name, Object oo) {
this.name = name;
this.oo = oo;
}
@Override
public void run() {
synchronized (this) {
for (int i = 0; i < 100; i++) {
System.out.println(name + i);
}
}
}
}
- 很容易验证我们的猜想和理解是正确的
# 再接下来我们看一下如果调用wait() 方法,应该是怎么个情况呢;
public class QQ {
public static void main(String[] args) {
Object oo = new Object();
Thread thread1 = new MyThread("thread1 -- ", oo);
thread1.start();
synchronized (oo) {
for (int i = 0; i < 100; i++) {
if (i == 20) {
try {
oo.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " -- " + i);
}
}
}
}
class MyThread extends Thread {
private String name;
private Object oo;
public MyThread(String name, Object oo) {
this.name = name;
this.oo = oo;
}
@Override
public void run() {
synchronized (oo) {
for (int i = 0; i < 100; i++) {
System.out.println(name + i);
}
oo.notifyAll();
}
}
}
- 乍一看,和调用join() 方法的现象一样;
- 嗯。。。有点意思了。。。
# 最后补充一点:jstack中的Thread-1 和 我们自己定义的 thread1 是不一样的,如果想要在jstack中显示我们自己定义的线程名, 则需要调用Thread的setName()方法
关于join() 是否会释放锁的一些思考的更多相关文章
- java多线程什么时候释放锁—wait()、notify()
由于等待一个锁定线程只有在获得这把锁之后,才能恢复运行,所以让持有锁的线程在不需要锁的时候及时释放锁是很重要的.在以下情况下,持有锁的线程会释放锁: 1. 执行完同步代码块. 2. 在执行 ...
- 【线程系列五】什么时候释放锁—wait()、notify()
由于等待一个锁定线程只有在获得这把锁之后,才能恢复运行,所以让持有锁的线程在不需要锁的时候及时释放锁是很重要的.在以下情况下,持有锁的线程会释放锁: 1. 执行完同步代码块. 2. 在执行 ...
- C++11 自动释放锁(转)
原文转自 https://blog.csdn.net/lmb1612977696/article/details/77712170 c++11加入了很多新的特性,值得我们去探索. 先看一个例子:普通的 ...
- Python 线程,with的作用(自动获取和释放锁Lock)
Python 线程,with的作用(自动获取和释放锁Lock) import threading import time num= #全局变量多个线程可以读写,传递数据 mutex=threading ...
- 【Java并发编程实战】----- AQS(二):获取锁、释放锁
上篇博客稍微介绍了一下AQS,下面我们来关注下AQS的所获取和锁释放. AQS锁获取 AQS包含如下几个方法: acquire(int arg):以独占模式获取对象,忽略中断. acquireInte ...
- ReentrantLock获取、释放锁的过程
看了篇文章,觉得分析得很透彻,其后总结的很到位,地址:http://www.iteye.com/topic/1083832 把获取与释放操作串在一起在简单看一下: 获取锁的时候将当前线程放入同步队列, ...
- 释放锁标记只有在Synchronized代码结束或者调用wait()。
释放锁标记只有在Synchronized代码结束或者调用wait(). 注意锁标记是自己不会自动释放,必须有通知. 注意在程序中判定一个条件是否成立时要注意使用WHILE要比使用IF要严密. WHIL ...
- Java关于ReentrantLock获取锁和释放锁源码跟踪
通过对ReentrantLock获取锁和释放锁源码跟踪主要想进一步深入学习AQS. 备注:AQS中的waitStatus状态码含义:
- Threed.sleep是不会释放锁,而wait是释放锁的(对象锁)
实战分析 一直都说,Threed.sleep是不会释放锁,而wait是释放锁的(对象锁),现理论上来分析一下啊. v package thread.concurrent; public class D ...
随机推荐
- Linux 之 netstat使用
netstat介绍 Netstat 命令用于显示各种网络相关信息,如网络连接,路由表,接口状态 (Interface Statistics),masquerade 连接,多播成员 (Multicast ...
- Vue触发隐藏input file的方法
1.使用input透明覆盖法 将input的z-index设置为1以上的数字并覆盖到需点击的内容上,将input的样式opacity设置为0(即为透明度为0),这样通过绑定在input上的change ...
- SQL FIND_IN_SET() 判断某一个数是否存在于数据表某个以逗号分隔开字段数据中
数据表中的字段存储的是以逗号分隔开的字符串, 例如 (1,2,6,8) 以前不知道这个用法, 碰到比如 8 是否包含在改字符串里面只能一个个取出来, 然后解析成数组,再判断是否在该数组中,效率极低: ...
- jupyter notebook 常用快捷操作
Shift-Enter 执行当前cell,并自动跳到下一个cell Ctrl-Enter 执行当前cell,执行后不自动调转到下一个cell DD 删除当前的cell L 为当前的cell加入line ...
- [github] 关于华为鸿蒙OS
English Docs | 中文文档 | Türkçe Dökümanlar HarmonyOS Ⅰ. 鸿蒙系统简介 鸿蒙系统(HarmonyOS),是第一款基于微内核的全场景分布式OS,是华为自主 ...
- 真理胜于一切 JAVA模拟表单提交
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import ...
- mysql8.0.13下载与安装图文教程
一.进入mysql网站:https://dev.mysql.com/downloads/mysql/ 二.进入Community选择MySQL Communtiy Server 三.将页面拉到最下面选 ...
- idea配置glassFish启动项目
将项目打成war包形式. 然后配置glassFish +号配置启动包 此处配置启动路径 ........ 路径也可以在localhost:4848 --->中的Applicaton中去配置
- java源码--ArrayList
1.1.ArrayList概述 1)ArrayList是可以动态增长和缩减的索引序列,它是基于数组实现的List类. 2)该类封装了一个动态再分配的Object[]数组,每一个类对象都有一个capac ...
- WDS无人参与批量部署Ser 2008
WDS无人参与批量部署Ser 2008 对于其它windows镜像采用此方法也是可以实现的: 1. 准备工作: 虚拟机server2012一个: 地址192.168.1.1/24 Server2008 ...