# 首先从一个很有意思的问题开始:

  - 问 : 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() 是否会释放锁的一些思考的更多相关文章

  1. java多线程什么时候释放锁—wait()、notify()

    由于等待一个锁定线程只有在获得这把锁之后,才能恢复运行,所以让持有锁的线程在不需要锁的时候及时释放锁是很重要的.在以下情况下,持有锁的线程会释放锁:    1. 执行完同步代码块.    2. 在执行 ...

  2. 【线程系列五】什么时候释放锁—wait()、notify()

    由于等待一个锁定线程只有在获得这把锁之后,才能恢复运行,所以让持有锁的线程在不需要锁的时候及时释放锁是很重要的.在以下情况下,持有锁的线程会释放锁:    1. 执行完同步代码块.    2. 在执行 ...

  3. C++11 自动释放锁(转)

    原文转自 https://blog.csdn.net/lmb1612977696/article/details/77712170 c++11加入了很多新的特性,值得我们去探索. 先看一个例子:普通的 ...

  4. Python 线程,with的作用(自动获取和释放锁Lock)

    Python 线程,with的作用(自动获取和释放锁Lock) import threading import time num= #全局变量多个线程可以读写,传递数据 mutex=threading ...

  5. 【Java并发编程实战】----- AQS(二):获取锁、释放锁

    上篇博客稍微介绍了一下AQS,下面我们来关注下AQS的所获取和锁释放. AQS锁获取 AQS包含如下几个方法: acquire(int arg):以独占模式获取对象,忽略中断. acquireInte ...

  6. ReentrantLock获取、释放锁的过程

    看了篇文章,觉得分析得很透彻,其后总结的很到位,地址:http://www.iteye.com/topic/1083832 把获取与释放操作串在一起在简单看一下: 获取锁的时候将当前线程放入同步队列, ...

  7. 释放锁标记只有在Synchronized代码结束或者调用wait()。

    释放锁标记只有在Synchronized代码结束或者调用wait(). 注意锁标记是自己不会自动释放,必须有通知. 注意在程序中判定一个条件是否成立时要注意使用WHILE要比使用IF要严密. WHIL ...

  8. Java关于ReentrantLock获取锁和释放锁源码跟踪

    通过对ReentrantLock获取锁和释放锁源码跟踪主要想进一步深入学习AQS. 备注:AQS中的waitStatus状态码含义:

  9. Threed.sleep是不会释放锁,而wait是释放锁的(对象锁)

    实战分析 一直都说,Threed.sleep是不会释放锁,而wait是释放锁的(对象锁),现理论上来分析一下啊. v package thread.concurrent; public class D ...

随机推荐

  1. flask的jinja2过滤器使用:遍历索引指定标签class属性,实现样式变化

    在flask项目中实现上图效果,采用使用自定义过滤器的形式对 span 标签的 class 指定. 1.定义过滤器 # common.py def do_index_class(index): &qu ...

  2. 图像欧拉数计算 matlab实现

    EUL = C - H 其中EUL表示欧拉数  C表示对象数 H表示孔洞数 欧拉数常用来识别数字: 识别数字 8 ,8 的欧拉数为 -1 ,不同于0,1,2,3,4,5,6,7,9 close all ...

  3. Egret入门学习日记 --- 第六篇(书中 3.6~3.9节 内容)

    第六篇(书中 3.6~3.9节 内容) 在本篇写之前,还是要为昨天写的日记道歉才行,差点就误人子弟了. 没想到在程序员界最低级的错误 “单词拼写错误” 还是会经常犯. childrenCreated ...

  4. XSSer:自动化XSS漏洞检测及利用工具

    转载自FreeBuf.COM XSS是一种非常常见的漏洞类型,它的影响非常的广泛并且很容易的就能被检测到. 攻击者可以在未经验证的情况下,将不受信任的JavaScript片段插入到你的应用程序中,然后 ...

  5. 【FFMPEG】Ubuntu上安装FFMPEG

    在之前,我们成功地使用mingw+msys在Windows平台下编译FFmpeg(见 http://www.linuxidc.com/Linux/2014-11/109839.htm),并生成了ffp ...

  6. TensorFlow.ZC尝试

    1.资料: https://github.com/protocolbuffers/protobuf/releases https://pythonprogramming.net/introductio ...

  7. WebForm——浅拷贝与深拷贝

    注:本文整理来自连接 https://www.cnblogs.com/echolun/p/7889848.html ,感谢博主的分享 总结: 1.浅拷贝:只拷贝变量的名,而不拷贝变量的值——常为引用类 ...

  8. 2019icpc南昌网络赛

    B. Fire-Fighting Hero (dijstra优先队列+bfs) 题意:刚开始看错题了,以为是k次dijkstra,但是wa了,后来队友指正后发现挺水的.求S到其它点的最短路的最大值an ...

  9. Nginx04---实现直播

    比如树莓派开启一个直播服务如何开启: 百度搜索:搭建自己的直播服务器(nginx + RTMP)

  10. Python 解LeetCode:33. Search in Rotated Sorted Array

    题目描述:在一个旋转数组中查找给定的值,其中旋转数组中不含重复值: 思路: 第一遍二分遍历,找到数组中最小值的索引: 第二遍分别对最小值左右两边的数组进行二分查找: class Solution(ob ...