面試 LockSupport.park()會釋放鎖資源嗎?

来源:https://www.cnblogs.com/tong-yuan/archive/2019/10/31/11768904.html
-Advertisement-
Play Games

(手機橫屏看源碼更方便) 引子 大家知道,我最近在招人,今天遇到個同學,他的源碼看過一些,然後我就開始了AQS連環問。 我:說說AQS的大致流程? 他:AQS包含一個狀態變數,一個同步隊列……balabala……互斥鎖balabala,共用鎖balabala…… 我:AQS中除了同步隊列,還有什麼隊 ...


park_thread

(手機橫屏看源碼更方便)


引子

大家知道,我最近在招人,今天遇到個同學,他的源碼看過一些,然後我就開始了AQS連環問。

我:說說AQS的大致流程?

他:AQS包含一個狀態變數,一個同步隊列……balabala……互斥鎖balabala,共用鎖balabala……

我:AQS中除了同步隊列,還有什麼隊列?

他:還有個Condition,Condition中有個條件隊列……

我:條件隊列和同步隊列有什麼區別?

他:條件隊列balabala,然後調用LockSupport.park()進入休眠,等待被喚醒,……,balabala

咦,這時我靈感突發:LockSupport.park()和Thread.sleep()有什麼區別?

他:Thread.sleep()不會釋放鎖資源,……,balabala

我:LockSupport.park()會釋放鎖資源嗎?

他:會吧。(估計和Object.wait()搞混淆了)

我:會嗎?會嗎?會嗎?

他(羞澀地低下了頭):彤哥,不知道,你的文章里沒寫。(這段我瞎寫的哈^^)

OK,今天我們就來看看LockSupport.park()到底會不會釋放鎖資源。

Thread.sleep()和Object.wait()的區別

首先,我們先來看看Thread.sleep()和Object.wait()的區別,這是一個爛大街的題目了,大家應該都能說上來兩點。

(1)Thread.sleep()不會釋放占有的鎖,Object.wait()會釋放占有的鎖;

(2)Thread.sleep()必須傳入時間,Object.wait()可傳可不傳,不傳表示一直阻塞下去;

(3)Thread.sleep()到時間了會自動喚醒,然後繼續執行;

(4)Object.wait()不帶時間的,需要另一個線程使用Object.notify()喚醒;

(5)Object.wait()帶時間的,假如沒有被notify,到時間了會自動喚醒,這時又分好兩種情況,一是立即獲取到了鎖,線程自然會繼續執行;二是沒有立即獲取鎖,線程進入同步隊列等待獲取鎖;

其實,他們倆最大的區別就是Thread.sleep()不會釋放鎖資源,Object.wait()會釋放鎖資源。

Thread.sleep()和Condition.await()的區別

我們再來看看Thread.sleep()和Condition.await()的區別。

其實,這個題目和上面的題目比較類似,因為本來Object.wait()和Condition.await()的原理就比較類似,可以參考之前彤哥寫的《死磕 java線程系列之線程的生命周期》之篇文章。

這個題目的回答思路跟Object.wait()是基本一致的,不同的是Condition.await()底層是調用LockSupport.park()來實現阻塞當前線程的。

實際上,它在阻塞當前線程之前還幹了兩件事,一是把當前線程添加到條件隊列中,二是“完全”釋放鎖,也就是讓state狀態變數變為0,然後才是調用LockSupport.park()阻塞當前線程,可以參考之前彤哥寫的《死磕 java同步系列之ReentrantLock源碼解析(二)——條件鎖》這篇文章。

看到這裡,今天開篇提的那個問題是不是就有答案了呢【本文由公從號“彤哥讀源碼”原創】?

Thread.sleep()和LockSupport.park()的區別

LockSupport.park()還有幾個兄弟方法——parkNanos()、parkUtil()等,我們這裡說的park()方法統稱這一類方法。

(1)從功能上來說,Thread.sleep()和LockSupport.park()方法類似,都是阻塞當前線程的執行,且都不會釋放當前線程占有的鎖資源

(2)Thread.sleep()沒法從外部喚醒,只能自己醒過來;

(3)LockSupport.park()方法可以被另一個線程調用LockSupport.unpark()方法喚醒;

(4)Thread.sleep()方法聲明上拋出了InterruptedException中斷異常,所以調用者需要捕獲這個異常或者再拋出;

(5)LockSupport.park()方法不需要捕獲中斷異常;

(6)Thread.sleep()本身就是一個native方法;

(7)LockSupport.park()底層是調用的Unsafe的native方法;

Object.wait()和LockSupport.park()的區別

二者都會阻塞當前線程的運行,他們有什麼區別呢?經過上面的分析相信你一定很清楚了,真的嗎?往下看!

(1)Object.wait()方法需要在synchronized塊中執行;

(2)LockSupport.park()可以在任意地方執行;

(3)Object.wait()方法聲明拋出了中斷異常,調用者需要捕獲或者再拋出;

(4)LockSupport.park()不需要捕獲中斷異常【本文由公從號“彤哥讀源碼”原創】;

(5)Object.wait()不帶超時的,需要另一個線程執行notify()來喚醒,但不一定繼續執行後續內容;

(6)LockSupport.park()不帶超時的,需要另一個線程執行unpark()來喚醒,一定會繼續執行後續內容;

(7)如果在wait()之前執行了notify()會怎樣?拋出IllegalMonitorStateException異常

(8)如果在park()之前執行了unpark()會怎樣?線程不會被阻塞,直接跳過park(),繼續執行後續內容;

最後兩點是不是沒想到?!

其實,在《死磕 java線程系列之自己動手寫一個線程池(續)》這篇文章里代碼註釋里稍微提到過unpark()這個方法,它先執行,則後續的park()方法將不再起作用。

park()/unpark()底層的原理是“二元信號量”,你可以把它相像成只有一個許可證的Semaphore,只不過這個信號量在重覆執行unpark()的時候也不會再增加許可證,最多只有一個許可證。

關於信號量的內容,可以參考《死磕 java同步系列之Semaphore源碼解析》這篇文章。

LockSupport.park()會釋放鎖資源嗎?

不會,它只負責阻塞當前線程,釋放鎖資源實際上是在Condition的await()方法中實現的。

彩蛋

好了,上面我們交叉對比了Thread.sleep()、Object.wait()、Condition.await()、LockSupport.park()的區別。

讓我們用一張思維導圖結束今天的內容。

park_thread


歡迎關註我的公眾號“彤哥讀源碼”,查看更多源碼系列文章, 與彤哥一起暢游源碼的海洋。

qrcode


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 場景 Ubuntu Server 16.04 LTS上怎樣安裝下載安裝Nginx並啟動: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/102828075 在上面進行安裝Nginx前配置檢查時提示: checking for C ...
  • 場景 Linux-安裝 Ubuntu Server 16.04 X64(圖文教程詳細版): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/93790806 Nginx入門簡介和反向代理、負載均衡、動靜分離理解: https://b ...
  • 安裝RabbitMQ,可以選擇使用Docker或者在CentOS下安裝RabbitMQ。這裡就不介紹這些高大上的安裝,就介紹在本地安裝吧。 第一步、下載並安裝erlang 為什麼要先下載安裝erlang呢?因為RabbitMQ服務端代碼是使用併發式語言Erlang編寫的,安裝RabbitMQ的前提是 ...
  • 事件起因 昨天有同事找我到,說他搭建的 XXL JOB 任務調度系統不能工作了,調用總是出錯(服務端返回 500)希望我能幫忙處理一下,不過說實話我也沒有搭建過 XXL JOB 的經驗,但是既然同事請求了,就只能硬著頭皮幫忙一起看下,解決的過程還算比較順利,但是發現網上這塊的資料很少,所以打算把解決 ...
  • 項目中要用到RabbitMQ,領導讓我先瞭解一下。在之前的公司中,用到過消息隊列MQ,阿裡的那款RocketMQ,當時公司也做了簡單的技術分享,自己也看了一些博客。自己在有道雲筆記上,做了一些整理,但後來也就擱在那了。現在有時間,就對MQ的一些簡單的概念做下整理吧。 RabbitMQ的一些介紹,請參 ...
  • 前段時間我朋友介紹我看一套b站Java教程 說這個教程是b站口碑最好的 我去看了一段時間 確實講的非常好 這套是求知講堂出的 網址:https://www.bilibili.com/video/av61604219 大家一起學習 有看過評價下這套教程 覺得他是不是b站最好的Java教程 ...
  • 今天,讓我們一起來探討 Java 併發編程中的知識點:volatile 關鍵字 本文主要從以下三點講解 volatile 關鍵字: 1. volatile 關鍵字是什麼? 2. volatile 關鍵字能解決什麼問題?使用場景是什麼? 3. volatile 關鍵字實現的原理? volatile 關 ...
  • 圖文簡介 邏輯關係 效果演示 快速開始 1、Spring Boot 應用暴露監控指標【版本 1.5.7.RELEASE】 首先,添加依賴如下依賴: 然後,在啟動類 添加如下註解: 最後,配置預設的登錄賬號和密碼,在 中: 提示:不建議配置 啟動應用程式後,會看到如下一系列的 Mappings 利用賬 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...