国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

Thread的Join方法原理

開發(fā) 前端
眾所周知,「Java的鎖其實本質(zhì)上是對象鎖」,因為我們前面調(diào)用的是thread.join(),所以這里的“鎖”對象其實thread這個對象。那這里wait釋放的是thread這個對象鎖。

[[410940]]

本文轉(zhuǎn)載自微信公眾號「編了個程」,作者Yasin x 。轉(zhuǎn)載本文請聯(lián)系編了個程公眾號。

Y說

今天沒什么要說的。我個人很喜歡拍天空的照片,放一張前段時間晚上拍的照片吧。

join方法釋放鎖嗎?

前段時間,有一個讀者私信我,問了這么一個問題:Thread實例的join方法內(nèi)部是調(diào)用的wait方法,而wait方法是會釋放鎖的,為什么網(wǎng)上很多文章(包括我們之前寫的開源書《深入淺出Java多線程》)會說join方法不釋放鎖?

釋放thread對象鎖

我們先用書中的一個例子說起:

  1. public class Join { 
  2.     static class ThreadA implements Runnable { 
  3.  
  4.         @Override 
  5.         public void run() { 
  6.             try { 
  7.                 System.out.println("我是子線程,我先睡一秒"); 
  8.                 Thread.sleep(1000); 
  9.                 System.out.println("我是子線程,我睡完了一秒"); 
  10.             } catch (InterruptedException e) { 
  11.                 e.printStackTrace(); 
  12.             } 
  13.         } 
  14.     } 
  15.  
  16.     public static void main(String[] args) throws InterruptedException { 
  17.         Thread thread = new Thread(new ThreadA()); 
  18.         thread.start(); 
  19.         thread.join(); 
  20.         System.out.println("如果不加join方法,我會先被打出來,加了就不一樣了"); 
  21.     } 

在這個例子中,我們在main方法中調(diào)用了thread.join(),打印出來的效果就是:

  1. 我是子線程,我先睡一秒 
  2. 我是子線程,我睡完了一秒 
  3. 如果不加join方法,我會先被打出來,加了就不一樣了 

這個例子想要表達的意圖很簡單,就是通過thread實例的join方法,達到main線程等待thread線程執(zhí)行完后再繼續(xù)執(zhí)行的效果。

那join方法底層是如何實現(xiàn)這個功能的呢?究竟會不會釋放鎖呢?我們點進去看看源碼。

  1. if (millis == 0) { 
  2.     while (isAlive()) { 
  3.         wait(0); 
  4.     } 
  5. else { 
  6.     while (isAlive()) { 
  7.         long delay = millis - now; 
  8.         if (delay <= 0) { 
  9.             break; 
  10.         } 
  11.         wait(delay); 
  12.         now = System.currentTimeMillis() - base; 
  13.     } 

可以看到,join的底層是調(diào)用的wait(long)方法。而wait方法是Object類型的實例方法,會釋放當前Object的鎖,且需要拿到當前Object的鎖才行。

這么說可能有點繞。眾所周知,「Java的鎖其實本質(zhì)上是對象鎖」,因為我們前面調(diào)用的是thread.join(),所以這里的“鎖”對象其實thread這個對象。那這里wait釋放的是thread這個對象鎖。

我們把上面的main方法簡單改一下,用另一個線程是占住thread這個對象鎖,就比較直觀了:

  1. public static void main(String[] args) throws InterruptedException { 
  2.     Thread thread = new Thread(new ThreadA()); 
  3.     thread.start(); 
  4.     new Thread(() -> { 
  5.         // 把thread對象作為鎖占住,這樣下面的join里面的wait只有等鎖釋放了才能執(zhí)行。 
  6.         synchronized (thread) { 
  7.             try { 
  8.                 System.out.println("我占住了thread鎖"); 
  9.                 Thread.sleep(10000); 
  10.                 System.out.println("我thread鎖釋放了"); 
  11.             } catch (InterruptedException e) { 
  12.                 e.printStackTrace(); 
  13.             } 
  14.         } 
  15.     }).start(); 
  16.     thread.join(); 
  17.     System.out.println("如果不加join方法,我會先被打出來,加了就不一樣了"); 

打印結(jié)果:

  1. 我是子線程,我先睡一秒 
  2. 我占住了thread鎖 
  3. 我是子線程,我睡完了一秒 
  4. 我thread鎖釋放了 
  5. 如果不加join方法,我會先被打出來,加了就不一樣了 

這就印證了那句話:wait方法執(zhí)行前,是需要獲取當前對象的鎖的。

所以回歸到最開始的問題:join()方法會釋放鎖嗎?嚴瑾的答案是它會釋放thread實例的對象鎖,但不會釋放其它對象鎖(包括main線程)。stackoverflow也對這個有討論:Does Thread.join() release the lock? Or continue to hold it?。

簡單來說,你說它釋放了鎖也對,因為它確實通過wait方法釋放了thread對象鎖,你說它沒釋放鎖也對,因為從調(diào)用線程的角度來看,它并沒有釋放當前調(diào)用線程持有的對象鎖。

當然,為了防止其它讀者看到這也有這個疑惑,我直接把文中的這句話刪掉了。

^image.png^

誰喚醒了?

源碼看到這,我又有了一個新的疑問:join方法內(nèi)部是一個while循環(huán)。wait釋放了鎖,那必然會有一個人來喚醒它,程序才能夠繼續(xù)往下走。那必然有一個地方調(diào)用了thread對象的notify方法。

我們在Thread類里面可以找到一個exit()方法,上面?zhèn)渥懼篢his method is called by the system to give a Thread a chance to clean up before it actually exits.

這么簡單的英文大家應該都能看懂吧?

里面有這么一段代碼:

  1. if (group != null) { 
  2.     group.threadTerminated(this); 
  3.     group = null
  4.  
  5. void threadTerminated(Thread t) { 
  6.     synchronized (this) { 
  7.         remove(t); 
  8.  
  9.         if (nthreads == 0) { 
  10.             notifyAll(); 
  11.         } 
  12.         if (daemon && (nthreads == 0) && 
  13.             (nUnstartedThreads == 0) && (ngroups == 0)) 
  14.         { 
  15.             destroy(); 
  16.         } 
  17.     } 

一開始我以為是在這里喚醒的,但仔細一看,這里調(diào)用的對象是ThreadGroup的實例,而不是thread實例。所以應該不是這個地方。

經(jīng)過一通google之后,我又在stackoverflow上找到了正確的答案(stackoverflow, yyds):who and when notify the thread.wait() when thread.join() is called?

答案顯示,這是在JVM層面去做的事:

  1. static void ensure_join(JavaThread* thread) { 
  2.   // We do not need to grap the Threads_lock, since we are operating on ourself. 
  3.   Handle threadObj(thread, thread->threadObj()); 
  4.   assert(threadObj.not_null(), "java thread object must exist"); 
  5.   ObjectLocker lock(threadObj, thread); 
  6.   // Ignore pending exception (ThreadDeath), since we are exiting anyway 
  7.   thread->clear_pending_exception(); 
  8.   // Thread is exiting. So set thread_status field in  java.lang.Thread class to TERMINATED. 
  9.   java_lang_Thread::set_thread_status(threadObj(), java_lang_Thread::TERMINATED); 
  10.   // Clear the native thread instance - this makes isAlive return false and allows the join() 
  11.   // to complete once we've done the notify_all below 
  12.   java_lang_Thread::set_thread(threadObj(), NULL); 
  13.   lock.notify_all(thread); 
  14.   // Ignore pending exception (ThreadDeath), since we are exiting anyway 
  15.   thread->clear_pending_exception(); 

可以看到除了notify_all以外,它其實做了很多掃尾的工作。包括處理異常、設(shè)置線程狀態(tài)等。

如果線程沒啟動

再把代碼改一下,如果線程沒有通過start啟動會怎樣呢?

  1. Thread thread = new Thread(new ThreadA()); 
  2. // thread.start(); 
  3. thread.join(); 
  4. System.out.println("如果不加join方法,我會先被打出來,加了就不一樣了"); 

會直接執(zhí)行最后一行代碼打印出來。

看join源碼就知道了,在wait之前,會有一個isAlive()的判斷,看當前線程是否是alive的。如果沒有start,那就會直接返回false,不進入wait。

總結(jié)

join方法會釋放thread對象鎖,底層是wait方法,在JVM層面通過notify_all來喚醒的。

 

責任編輯:武曉燕 來源: 編了個程
相關(guān)推薦

2023-05-08 00:08:51

Hive機制場景

2024-05-28 00:00:02

Java線程程序

2009-06-29 18:08:51

Java多線程join方法

2009-04-02 10:23:13

實現(xiàn)JoinMySQL

2017-08-31 16:17:35

SQL優(yōu)化器原理

2018-01-25 19:09:40

JavaThreadLocal線程

2009-05-07 15:02:42

OracleJoin查詢

2009-08-26 16:58:12

調(diào)用C# Thread

2023-06-07 07:43:57

數(shù)據(jù)庫JOIN類型

2023-07-03 08:10:51

2010-05-21 17:30:28

2021-09-10 06:50:03

HashMapHash方法

2011-06-22 15:42:18

QT 信號

2016-12-21 14:35:46

響應式網(wǎng)頁布局實現(xiàn)方法原理

2013-03-11 10:07:36

主干交換機交換機工作原理交換機設(shè)備

2021-10-15 11:37:44

反爬蟲破解

2023-08-08 00:06:31

2022-03-30 08:54:21

線程 Thread判斷線程池任務Java

2025-08-13 06:00:00

Flink SQLFlink大數(shù)據(jù)

2012-02-01 14:28:03

Java線程
點贊
收藏

51CTO技術(shù)棧公眾號

夜夜嗨av一区二区三区四季av | 性欧美hd调教| 视频二区在线| 在线观看小视频| 色www永久免费视频首页在线| 亚洲a∨精品一区二区三区导航| 日韩另类视频| 久久99蜜桃| 日韩成人精品一区| 日日夜夜精品免费视频| 久久综合999| 欧美性xxxx在线播放| 7777精品伊人久久久大香线蕉完整版| 日韩成人小视频| 久久成年人免费电影| 日韩影片在线播放| 九色视频一区| 深夜成人在线| 亚洲少妇自拍| 婷婷成人激情在线网| 久久国产精品偷| 国产三级精品在线不卡| 三级黄色的网站| 国产精品色在线网站| 蜜乳av一区二区三区| 日韩一区二区在线观看| 成人在线看片| 91大神网址| 日韩精品免费播放| 国产传媒在线播放| 久久99影视| 夜夜亚洲天天久久| 久久高清视频免费| 国产免费黄色一级片| 久久电影网站| 国产成人精品午夜视频免费| 欧美一级午夜免费电影| 国产福利精品视频| eeuss鲁片一区| 视频精品一区| 成人av网站在线观看免费| 亚洲第一偷拍网| 欧美日韩中文字幕在线播放| 日本一级理论片在线大全| av福利精品导航| 91精品视频在线| 欧美国产一级| 麻豆映画在线观看| 精品福利樱桃av导航| 牛牛电影国产一区二区| 久久久久久久一| 秋霞电影网一区二区| 亚洲最大综合网| 日韩视频不卡中文| 91精品国产乱码久久久久久| 强开小嫩苞一区二区三区网站| 午夜av一区二区三区| 热久久久久久| 丝袜足脚交91精品| 亚洲综合色区另类av| 欧美成人国产一区二区| 正在播放亚洲| 日本一区中文字幕| 亚洲精品免费在线视频| 啪啪免费视频一区| 91网上在线视频| 欧美日韩亚洲一区二区三区四区| 日本a人精品| 日韩午夜中文字幕| 牛牛影视精品影视| 成人污污视频在线观看| 精品一区二区三区自拍图片区 | 欧美xfplay| 日韩深夜福利网站| 91久久久久久| 成人午夜免费电影| 日本一区二区三区在线观看视频| 亚洲国产中文字幕久久网| 精品精品精品| 欧洲亚洲一区| 国产精品亲子乱子伦xxxx裸| 日本亚洲欧美成人| 久久密一区二区三区| 老汉色影院首页| 一区二区三区欧美| 天堂av中文在线观看| 国产精品亚洲一区二区三区| 国产1区2区3区精品美女| 欧美日韩影视| 欧美国产视频日韩| 日本欧美在线观看| 亚洲图片123| 欧美裸体xxxx极品少妇| 久久九九精品| 色网址在线观看| x99av成人免费| 久久亚洲影院| 婷婷亚洲一区二区三区| 俺去亚洲欧洲欧美日韩| 99综合视频| 日本一二区视频| 久久久精品电影| 卡一卡二国产精品| 日韩免费啪啪| 国产精品女人网站| 国产精品网站一区| 高清全集视频免费在线| 神马影院午夜我不卡影院| 日产午夜精品一线二线三线| 成年人网站国产| 日韩亚洲欧美在线观看| 久久精品久久久| 欧美一区日本一区韩国一区| 日韩一区中文| 亚洲一区二区三区涩| 91高清视频在线| 91嫩草亚洲精品| 成视频免费在线看| 欧美黑人xxx| 9l国产精品久久久久麻豆| 三妻四妾完整版在线观看电视剧| 看欧美日韩国产| 欧美视频一区二区三区| 天天影视欧美综合在线观看| 成年人视频在线| 欧美高清在线观看| 久久免费电影网| 欧美区一区二区| 国产一区视频免费观看| 欧美成人精品激情在线观看| 99久久er热在这里只有精品15| 成人免费网站视频| 免费观看国产视频在线| 国产视频精品在线| 国产美女一区二区| 刘亦菲一区二区三区免费看| 一级性生活视频| 中国china体内裑精亚洲片| 成人综合在线网站| 国产情侣一区在线| 久久久久久久少妇| 51色欧美片视频在线观看| 亚洲视频在线观看一区| 欧美综合久久| 国产youjizz在线| 欧美日韩一区二区三区在线观看免| 欧美一三区三区四区免费在线看| 欧美专区一区二区三区| 污片在线免费观看| 日韩一级片一区二区| 一本色道久久88综合亚洲精品ⅰ | 国产精品一区久久| 精品久久久香蕉免费精品视频| 99精品小视频| 日本福利在线| 久久久一二三四| www.亚洲男人天堂| 亚洲欧洲在线观看av| 国内精品久久久久久久久电影网| 欧美日本网站| 一区二区三区的久久的视频| 中文字幕精品久久| 最新久久zyz资源站| 欧美激情 亚洲a∨综合| www.久久久久.com| 欧美精品卡一卡二| 欧美孕妇与黑人孕交| 狠狠躁夜夜躁人人爽超碰91| 久久最新视频| 久久免费资源| 最美情侣韩剧在线播放| 欧美精品在线一区| 主播福利视频一区| 一区二区三区中文免费| 在线综合亚洲| 国产亚洲人成a在线v网站 | 国产精品偷伦视频免费观看国产 | 中文字幕亚洲综合久久五月天色无吗''| 春暖花开成人亚洲区| 亚洲欧美一二三| 久久免费精品日本久久中文字幕| 高跟丝袜一区二区三区| 精品无人码麻豆乱码1区2区| 99国产精品免费网站| 成黄免费在线| 久久久999免费视频| 91在线免费看片| 一个色综合导航| 亚洲成人免费av| 激情小说亚洲一区| 天堂俺去俺来也www久久婷婷| 风间由美一区| 日本精品www| 国产青春久久久国产毛片| 久久精品视频导航| 欧美视频在线不卡| 中文字幕免费不卡在线| 日韩黄色一级片| 国产伦精品一区二区三区视频| 天堂√中文最新版在线|