多線程問題整理

来源:https://www.cnblogs.com/zhaoran8775/archive/2020/05/06/12839660.html
-Advertisement-
Play Games

1.如何實現一個生產者和消費者模型?(鎖、信號量、線程通信、阻塞隊列等) "Java生產者和消費者模型的5種實現方式" 2.如何理解線程的同步和非同步、阻塞和非阻塞? 作者:Yi Lu 鏈接:https://www.zhihu.com/question/19732473/answer/20851256 ...


1.如何實現一個生產者和消費者模型?(鎖、信號量、線程通信、阻塞隊列等)

Java生產者和消費者模型的5種實現方式

2.如何理解線程的同步和非同步、阻塞和非阻塞?

作者:Yi Lu
鏈接:https://www.zhihu.com/question/19732473/answer/20851256
來源:知乎

“阻塞”與"非阻塞"與"同步"與“非同步"不能簡單的從字面理解,提供一個從分散式系統角度的回答。
1.同步與非同步
同步和非同步關註的是消息通信機制 (synchronous communication/ asynchronous communication)
所謂同步,就是在發出一個調用時,在沒有得到結果之前,該調用就不返回。但是一旦調用返回,就得到返回值了。
換句話說,就是由調用者主動等待這個調用的結果。

而非同步則是相反,調用*在發出之後,這個調用就直接返回了,所以沒有返回結果。換句話說,當一個非同步過程調用發出後,調用者不會立刻得到結果。而是在調用發出後,被調用者*通過狀態、通知來通知調用者,或通過回調函數處理這個調用。

典型的非同步編程模型比如Node.js

舉個通俗的例子:
你打電話問書店老闆有沒有《分散式系統》這本書,如果是同步通信機制,書店老闆會說,你稍等,”我查一下",然後開始查啊查,等查好了(可能是5秒,也可能是一天)告訴你結果(返回結果)。
而非同步通信機制,書店老闆直接告訴你我查一下啊,查好了打電話給你,然後直接掛電話了(不返回結果)。然後查好了,他會主動打電話給你。在這裡老闆通過“回電”這種方式來回調。

  1. 阻塞與非阻塞

    阻塞和非阻塞關註的是程式在等待調用結果(消息,返回值)時的狀態.

阻塞調用是指調用結果返回之前,當前線程會被掛起。調用線程只有在得到結果之後才會返回。
非阻塞調用指在不能立刻得到結果之前,該調用不會阻塞當前線程。

還是上面的例子,
你打電話問書店老闆有沒有《分散式系統》這本書,你如果是阻塞式調用,你會一直把自己“掛起”,直到得到這本書有沒有的結果,如果是非阻塞式調用,你不管老闆有沒有告訴你,你自己先一邊去玩了, 當然你也要偶爾過幾分鐘check一下老闆有沒有返回結果。
在這裡阻塞與非阻塞與是否同步非同步無關。跟老闆通過什麼方式回答你結果無關。

如果是關心阻塞 IO/ 非同步 IO, 參考 Unix Network Programming View Book

還是2014年寫的以解釋概念為主,主要是同步非同步 阻塞和非阻塞會被用在不同層面上,可能會有不准確的地方,並沒有針對 阻塞 IO/ 非同步 IO 等進行討論,大家可以後續看看這兩個回答:

怎樣理解阻塞非阻塞與同步非同步的區別?

怎樣理解阻塞非阻塞與同步非同步的區別?

3.線程池處理任務的流程是怎樣的?

1,首先線程池判斷基本線程池是否已滿(< corePoolSize ?)?沒滿,創建一個工作線程來執行任務。滿了,則進入下個流程。

2,其次線程池判斷工作隊列是否已滿?沒滿,則將新提交的任務存儲在工作隊列里。滿了,則進入下個流程。

3,最後線程池判斷整個線程池是否已滿(< maximumPoolSize ?)?沒滿,則創建一個新的工作線程來執行任務,滿了,則交給飽和策略來處理這個任務。

總結:線程池優先要創建出基本線程池大小(corePoolSize)的線程數量,沒有達到這個數量時,每次提交新任務都會直接創建一個新線程,當達到了基本線程數量後,又有新任務到達,優先放入等待隊列,如果隊列滿了,才去創建新的線程(不能超過線程池的最大數maxmumPoolSize)

4.wait和sleep有什麼不同?

區別1:使用限制

使用 sleep 方法可以讓讓當前線程休眠,時間一到當前線程繼續往下執行,在任何地方都能使用,但需要捕獲 InterruptedException 異常。

try {
    Thread.sleep(3000L);
} catch (InterruptedException e) {
    e.printStackTrace();
}

而使用 wait 方法則必須放在 synchronized 塊裡面,同樣需要捕獲 InterruptedException 異常,並且需要獲取對象的鎖。

synchronized (lock){
    try {
        lock.wait();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

而且 wait 還需要額外的方法 notify/ notifyAll 進行喚醒,它們同樣需要放在 synchronized 塊裡面,且獲取對象的鎖。。

synchronized (lock) {
    // 隨機喚醒
    lock.notify();

    // 喚醒全部
    lock.notifyAll();
}

當然也可以使用帶時間的 wait(long millis) 方法,時間一到,無需其他線程喚醒,也會重新競爭獲取對象的鎖繼續執行。

區別2:使用場景

sleep 一般用於當前線程休眠,或者輪循暫停操作,wait 則多用於多線程之間的通信。

區別3:所屬類

sleep 是 Thread 類的靜態本地方法,wait 則是 Object 類的本地方法。

java.lang.Thread#sleep

public static native void sleep(long millis) throws InterruptedException;

java.lang.Object#wait

public final native void wait(long timeout) throws InterruptedException;

為什麼要這樣設計呢?

因為 sleep 是讓當前線程休眠,不涉及到對象類,也不需要獲得對象的鎖,所以是線程類的方法。wait 是讓獲得對象鎖的線程實現等待,前提是要楚獲得對象的鎖,所以是類的方法。

區別4:釋放鎖

Object lock = new Object();
synchronized (lock) {
    try {
        lock.wait(3000L);
        Thread.sleep(2000L);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

如上代碼所示,wait 可以釋放當前線程對 lock 對象鎖的持有,而 sleep 則不會。

區別5:線程切換

sleep 會讓出 CPU 執行時間且強制上下文切換,而 wait 則不一定,wait 後可能還是有機會重新競爭到鎖繼續執行的。

5.Synchronized和ReentrantLock有什麼不同?各適合什麼場景?

1、ReentrantLock 擁有Synchronized相同的併發性和記憶體語義,此外還多了鎖投票定時鎖等候中斷鎖等候
example:線程A和B都要獲取對象O的鎖定,假設A獲取了對象O鎖,B將等待A釋放對O的鎖定,如果使用 synchronized ,如果A不釋放,B將一直等下去,不能被中斷如果 使用ReentrantLock,如果A不釋放,可以使B在等待了足夠長的時間以後,中斷等待,而乾別的事情
ReentrantLock獲取鎖定與三種方式:
  • lock(), 如果獲取了鎖立即返回,如果別的線程持有鎖,當前線程則一直處於休眠狀態,直到獲取鎖
  • tryLock(), 如果獲取了鎖立即返回true,如果別的線程正持有鎖,立即返回false;
  • tryLock(long timeout,TimeUnit unit), 如果獲取了鎖定立即返回true,如果別的線程正持有鎖,會等待參數給定的時間,在等待的過程中,如果獲取了鎖定,就返回true,如果等待超時,返回false;
  • lockInterruptibly:如果獲取了鎖定立即返回,如果沒有獲取鎖定,當前線程處於休眠狀態,直到或者鎖定,或者當前線程被別的線程中斷

2、synchronized是在JVM層面上實現的,不但可以通過一些監控工具監控synchronized的鎖定,而且在代碼執行時出現異常,JVM會自動釋放鎖定,但是使用Lock則不行,lock是通過代碼實現的,要保證鎖定一定會被釋放,就必須將unLock()放到finally{}中

3、在資源競爭不是很激烈的情況下,Synchronized的性能要優於ReetrantLock,但是在資源競爭很激烈的情況下,Synchronized的性能會下降幾十倍,但是ReetrantLock的性能能維持常態;

作者:OverLight
鏈接:https://www.jianshu.com/p/4dbacf1cadcf
來源:簡書

6.讀寫鎖適用於什麼場景?ReentrantReadWriteLock是如何實現的?

ReentrantReadWriteLock讀寫鎖詳解

7.線程之間如何通信?

[JAVA多線程之線程間的通信方式](https://www.cnblogs.com/hapjin/p/5492619.html)

8.保證線程安全的方法有哪些?

如何保證線程安全

9.如何儘可能提高多線程併發性能?

如何提高Java並行程式性能

10.ThreadLocal用來解決什麼問題?ThreadLocal是如何實現的?

ThreadLocal

11.死鎖的產生條件?如何分析是否有線程死鎖?

Java 多線程死鎖的產生以及如何避免死鎖

12.在實際工作中遇到過什麼樣的併發問題,如何發現(排查)並解決的?

[Java面試 32個核心必考點完全解析


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

-Advertisement-
Play Games
更多相關文章
  • 結合個人經歷總結的前端入門方法,總結從零基礎到具備前端基本技能的道路、學習方法、資料。由於能力有限,不能保證面面俱到,只是作為入門參考,面向初學者,讓初學者少走彎路。 互聯網的快速發展和激烈競爭,用戶體驗成為一個重要的關註點,導致專業前端工程師成為熱門職業,各大公司對前端工程師的需求量都很大,要求也 ...
  • 上一篇文章,介紹了這個架構中,WebServer的選擇,以及整個架構中擴展時的思路。 原文地址:15分鐘從零開始搭建支持10w+用戶的生產環境(三) 五、架構實踐 前邊用了三篇文章,詳細介紹了這個架構的各個部分的選擇以及安裝。 這篇文章,我會用一個Demo項目,從開發到部署,包括MongoDB數據的 ...
  • 使用 kind 快速搭建 Kubernetes 環境 Intro kind(Kubernetes IN Docker) 是一個基於 docker 構建 Kubernetes 集群的工具,非常適合用來在本地搭建基於 Kubernetes 的開發/測試環境。 想寫一篇 kind 的文章很久了,但是之前的 ...
  • 因為QT的三維顯示模塊QtDataVisualization已經對個人開發免費開放了,所以在製作點雲,地圖,表格之類的東西的時候,其實我們都不需要使用QtCharts或者QOpenGL模塊了。直接使用QtDataVisualization模塊非常的方便。 正好最近需要製作一個點雲顯示器,我就按照官方 ...
  • 我的LeetCode:https://leetcode cn.com/u/ituring/ 我的LeetCode刷題源碼[GitHub]:https://github.com/izhoujie/Algorithmcii LeetCode 983. 最低票價 題目 在一個火車旅行很受歡迎的國度,你提前 ...
  • 一、反射 1.在Java虛擬機種,只有一個類,所有使用使用反射機制的時候,創建多少個引用都是指向同一個類的。 2​.通過Class類對象創建java對象 package com.bjpowernode.java_learning; import com.bjpowernode.java_learni ...
  • 沒有了with表達,with,exp,body的id換成exp的lambda函數,從而可以沒有with來進行實現。即,{with {id exp} body}換成了{{fun {id} body} exp}。 FAE : Concrete syntax FAE : Abstrac syntax pa ...
  • EL表達式 1. 概念:Expression Language 表達式語言 2. 作用:替換和簡化jsp頁面中的java代碼的編寫 3. 語法${表達式} 4. 註意: jsp預設支持el表達式。如果要忽略el表達式 1. 設置jsp中page指令中:isELIgnored=“true”忽略當前js ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...