欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java面試題沖刺第二十五天--并發(fā)編程2

 更新時(shí)間:2021年08月09日 14:30:45   作者:_陳哈哈  
這篇文章主要為大家分享了最有價(jià)值的三道關(guān)于并發(fā)編程的面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,感興趣的小伙伴們可以參考一下

面試題1:簡單說下你對線程和進(jìn)程的理解?

正經(jīng)回答:

在這里插入圖片描述

進(jìn)程

  • 一個(gè)在內(nèi)存中運(yùn)行的應(yīng)用程序。每個(gè)進(jìn)程都有自己獨(dú)立的一塊內(nèi)存空間,一個(gè)進(jìn)程可以有多個(gè)線程,比如在Windows系統(tǒng)中,一個(gè)運(yùn)行的xx.exe就是一個(gè)進(jìn)程。

線程

  • 進(jìn)程中的一個(gè)執(zhí)行任務(wù)(控制單元),負(fù)責(zé)當(dāng)前進(jìn)程中程序的執(zhí)行。一個(gè)進(jìn)程至少有一個(gè)線程,一個(gè)進(jìn)程可以運(yùn)行多個(gè)線程,多個(gè)線程可共享數(shù)據(jù)。

深入追問:

追問1:那進(jìn)程和線程有哪些區(qū)別呢?

想起了某乎上的經(jīng)典回答:

做個(gè)簡單的比喻:進(jìn)程 → 火車,線程 → 車廂;線程在進(jìn)程下行進(jìn)(單純的車廂無法運(yùn)行)

  • 一個(gè)進(jìn)程可以包含多個(gè)線程(一輛火車可以有多個(gè)車廂)
  • 不同進(jìn)程間數(shù)據(jù)很難共享(一輛火車上的乘客很難換到另外一輛火車,比如站點(diǎn)換乘)
  • 同一進(jìn)程下不同線程間數(shù)據(jù)很易共享(A車廂換到B車廂很容易)
  • 進(jìn)程要比線程消耗更多的計(jì)算機(jī)資源(采用多列火車相比多個(gè)車廂更耗資源)

在這里插入圖片描述

  • 進(jìn)程間不會相互影響,一個(gè)線程掛掉將導(dǎo)致整個(gè)進(jìn)程掛掉(一列火車不會影響到另外一列火車,但是如果一列火車上中間的一節(jié)車廂著火了,將影響到所有車廂)
  • 進(jìn)程可以拓展到多機(jī),線程最多擴(kuò)展到多核CPU,而不能擴(kuò)展到多機(jī)(不同火車可以開在多個(gè)軌道上,同一火車的車廂不能在行進(jìn)的不同的軌道上)
  • 進(jìn)程使用的內(nèi)存地址可以上鎖,即一個(gè)線程使用某些共享內(nèi)存時(shí),其他線程必須等它結(jié)束,才能使用這一塊內(nèi)存。(比如火車上的洗手間)-“互斥鎖”
  • 進(jìn)程使用的內(nèi)存地址可以限定使用量(比如火車上的餐廳,最多只允許多少人進(jìn)入,如果滿了需要在門口等,等有人出來了才能進(jìn)去)-“信號量”

面試題2:守護(hù)線程和用戶線程的區(qū)別? 正經(jīng)回答:

用戶 (User) 線程:

  • 運(yùn)行在前臺,執(zhí)行具體的任務(wù),如程序的主線程、連接網(wǎng)絡(luò)的子線程等都是用戶線程

守護(hù) (Daemon) 線程:

  • 運(yùn)行在后臺,為其他前臺線程(非守護(hù)線程)服務(wù)。當(dāng)所有用戶線程都結(jié)束運(yùn)行時(shí),守護(hù)線程會隨 JVM 一起結(jié)束工作.

可見,守護(hù)線程是依賴于用戶線程,當(dāng)所有用戶線程都退出了,守護(hù)線程也就會退出,典型的守護(hù)線程如垃圾回收線程。

而用戶線程是獨(dú)立存在的,不會因?yàn)槠渌脩艟€程退出而退出。

注意事項(xiàng):

  • setDaemon(true)必須在start()方法前執(zhí)行,否則會拋出 IllegalThreadStateException 異常
  • 在守護(hù)線程中產(chǎn)生的新線程也是守護(hù)線程
  • 不是所有的任務(wù)都可以分配給守護(hù)線程來執(zhí)行,比如讀寫操作或者計(jì)算邏輯
  • 守護(hù) (Daemon) 線程中不能依靠 finally 塊的內(nèi)容來確保執(zhí)行關(guān)閉或清理資源的邏輯。因?yàn)槲覀兩厦嬉舱f過了一旦所有用戶線程都結(jié)束運(yùn)行,守護(hù)線程會隨 JVM 一起結(jié)束工作,所以守護(hù) (Daemon) 線程中的 finally 語句塊可能無法被執(zhí)行。

面試題3:什么是線程死鎖?

正經(jīng)回答:

死鎖是指兩個(gè)或兩個(gè)以上的進(jìn)程(線程)在執(zhí)行過程中,由于競爭資源或者由于彼此通信而造成的一種阻塞的現(xiàn)象,若無外力作用,它們都將無法推進(jìn)下去。此時(shí)稱系統(tǒng)處于死鎖狀態(tài)或系統(tǒng)產(chǎn)生了死鎖,這些永遠(yuǎn)在互相等待的進(jìn)程(線程)稱為死鎖進(jìn)程(線程)。

例如,在某個(gè)計(jì)算機(jī)系統(tǒng)中只有一臺打印機(jī)和一臺輸入 設(shè)備,進(jìn)程A正占用輸入設(shè)備,同時(shí)又提出使用打印機(jī)的請求,但此時(shí)打印機(jī)正被進(jìn)程B 所占用,而B在未釋放打印機(jī)之前,又提出請求使用正被A占用著的輸入設(shè)備。這樣兩個(gè)進(jìn)程相互無休止地等待下去,均無法繼續(xù)執(zhí)行,此時(shí)兩個(gè)進(jìn)程陷入死鎖狀態(tài)。

多個(gè)線程同時(shí)被阻塞,它們中的一個(gè)或者全部都在等待某個(gè)資源被釋放。由于線程被無限期地阻塞,因此程序不可能正常終止。

如下圖所示,線程 A 持有資源 2,線程 B 持有資源 1,他們同時(shí)都想申請對方的資源,所以這兩個(gè)線程就會互相等待而進(jìn)入死鎖狀態(tài)。

在這里插入圖片描述

下面是一個(gè)死鎖示例代碼:

// 示例來自《并發(fā)編程之美》
public class DeadLockDemo {
    private static Object resource1 = new Object();//資源 1
    private static Object resource2 = new Object();//資源 2

    public static void main(String[] args) {
        new Thread(() -> {
            synchronized (resource1) {
                System.out.println(Thread.currentThread() + "get resource1");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread() + "waiting get resource2");
                synchronized (resource2) {
                    System.out.println(Thread.currentThread() + "get resource2");
                }
            }
        }, "線程 1").start();

        new Thread(() -> {
            synchronized (resource2) {
                System.out.println(Thread.currentThread() + "get resource2");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread() + "waiting get resource1");
                synchronized (resource1) {
                    System.out.println(Thread.currentThread() + "get resource1");
                }
            }
        }, "線程 2").start();
    }
}

打印輸出:

Thread[線程 1,5,main]get resource1
Thread[線程 2,5,main]get resource2
Thread[線程 1,5,main]waiting get resource2
Thread[線程 2,5,main]waiting get resource1

線程 A 通過 synchronized (resource1) 獲得 resource1 的監(jiān)視器鎖,然后通過Thread.sleep(1000);讓線程 A 休眠 1s 為的是讓線程 B 得到CPU執(zhí)行權(quán),從而獲取到 resource2 的監(jiān)視器鎖。

線程 A 和線程 B 休眠結(jié)束了都開始企圖請求獲取對方的資源,然后這兩個(gè)線程就會陷入互相等待的狀態(tài),這也就產(chǎn)生了死鎖。上面的例子符合產(chǎn)生死鎖的四個(gè)必要條件。

深入追問:

追問1:形成死鎖的四個(gè)必要條件是什么? 

  • 互斥: 某種資源一次只允許一個(gè)進(jìn)程訪問,即該資源一旦分配給某個(gè)進(jìn)程,其他進(jìn)程就不能再訪問,直到該進(jìn)程訪問結(jié)束。
  • 占有且等待: 一個(gè)進(jìn)程本身占有資源(一種或多種),同時(shí)還有資源未得到滿足,正在等待其他進(jìn)程釋放該資源。
  • 不可搶占: 別人已經(jīng)占有了某項(xiàng)資源,你不能因?yàn)樽约阂残枰撡Y源,就去把別人的資源搶過來。
  • 循環(huán)等待: 存在一個(gè)進(jìn)程鏈,使得每個(gè)進(jìn)程都占有下一個(gè)進(jìn)程所需的至少一種資源。

當(dāng)以上四個(gè)條件均滿足,必然會造成死鎖,相反,而只要上述條件之一不滿足,就不會發(fā)生死鎖。

發(fā)生死鎖的進(jìn)程無法進(jìn)行下去,它們所持有的資源也無法釋放。這樣會導(dǎo)致CPU的吞吐量下降。所以死鎖情況是會浪費(fèi)系統(tǒng)資源和影響計(jì)算機(jī)的使用性能的。

追問2:我們該如何避免死鎖?

死鎖避免的基本思想:系統(tǒng)對進(jìn)程發(fā)出每一個(gè)系統(tǒng)能夠滿足的資源申請進(jìn)行動(dòng)態(tài)檢查,并根據(jù)檢查結(jié)果決定是否分配資源,如果分配后系統(tǒng)可能發(fā)生死鎖,則不予分配,否則予以分配。這是一種保證系統(tǒng)不進(jìn)入死鎖狀態(tài)的動(dòng)態(tài)策略。

理解了死鎖的原因,尤其是產(chǎn)生死鎖的四個(gè)必要條件,就可以最大可能地避免、預(yù)防和解除死鎖。只要打破四個(gè)必要條件之一就能有效預(yù)防死鎖的發(fā)生:

  • 打破互斥條件:改造獨(dú)占性資源為虛擬資源,大部分資源已無法改造。
  • 打破不可搶占條件:當(dāng)一進(jìn)程占有一獨(dú)占性資源后又申請一獨(dú)占性資源而無法滿足,則退出原占有的資源。
  • 打破占有且等待條件:采用資源預(yù)先分配策略,即進(jìn)程運(yùn)行前申請全部資源,滿足則運(yùn)行,不然就等待,這樣就不會占有且申請。
  • 打破循環(huán)等待條件:實(shí)現(xiàn)資源有序分配策略,對所有設(shè)備實(shí)現(xiàn)分類編號,所有進(jìn)程只能采用按序號遞增的形式申請資源。

追問3:死鎖避免和死鎖預(yù)防有啥不同?

死鎖預(yù)防是設(shè)法至少破壞產(chǎn)生死鎖的四個(gè)必要條件之一,嚴(yán)格的防止死鎖的出現(xiàn);而死鎖避免則不那么嚴(yán)格的限制產(chǎn)生死鎖的必要條件的存在,因?yàn)榧词顾梨i的必要條件存在,也不一定發(fā)生死鎖。死鎖避免是在系統(tǒng)運(yùn)行過程中注意避免死鎖的最終發(fā)生。

總結(jié)

本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • 初探Spring Cloud Gateway實(shí)戰(zhàn)

    初探Spring Cloud Gateway實(shí)戰(zhàn)

    這篇文章主要介紹了創(chuàng)建網(wǎng)關(guān)項(xiàng)目(Spring Cloud Gateway)過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2021-08-08
  • aop注解方式實(shí)現(xiàn)全局日志管理方法

    aop注解方式實(shí)現(xiàn)全局日志管理方法

    下面小編就為大家分享一篇aop注解方式實(shí)現(xiàn)全局日志管理方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-01-01
  • JDK1.8、JDK1.7、JDK1.6區(qū)別看這里

    JDK1.8、JDK1.7、JDK1.6區(qū)別看這里

    這篇文章主要為大家詳細(xì)介紹了JDK1.8、JDK1.7、JDK1.6中的源碼,對比閱讀,發(fā)現(xiàn)修改問題以及改進(jìn)點(diǎn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • JMeter斷言之json斷言解讀

    JMeter斷言之json斷言解讀

    這篇文章主要介紹了JMeter斷言之json斷言問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Java詳細(xì)講解不同版本的接口語法和抽象類與接口的區(qū)別

    Java詳細(xì)講解不同版本的接口語法和抽象類與接口的區(qū)別

    對于面向?qū)ο缶幊虂碚f,抽象是它的一大特征之一,在?Java?中可以通過兩種形式來體現(xiàn)OOP的抽象:接口和抽象類,下面這篇文章主要給大家介紹了關(guān)于Java入門基礎(chǔ)之抽象類與接口的相關(guān)資料,需要的朋友可以參考下
    2022-04-04
  • Spring Security 表單登錄功能的實(shí)現(xiàn)方法

    Spring Security 表單登錄功能的實(shí)現(xiàn)方法

    這篇文章主要介紹了Spring Security 表單登錄,本文將構(gòu)建在之前簡單的 Spring MVC示例 之上,因?yàn)檫@是設(shè)置Web應(yīng)用程序和登錄機(jī)制的必不可少的。需要的朋友可以參考下
    2019-06-06
  • 基于ArrayList源碼解析(基于JDK1.8)

    基于ArrayList源碼解析(基于JDK1.8)

    這篇文章主要介紹了關(guān)于ArrayList源碼解析(基于JDK1.8),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • java.lang.Instrument 代理Agent使用詳細(xì)介紹

    java.lang.Instrument 代理Agent使用詳細(xì)介紹

    這篇文章主要介紹了java.lang.Instrument 代理Agent使用詳細(xì)介紹的相關(guān)資料,附有實(shí)例代碼,幫助大家學(xué)習(xí)參考,需要的朋友可以參考下
    2016-11-11
  • 老生常談Java虛擬機(jī)垃圾回收機(jī)制(必看篇)

    老生常談Java虛擬機(jī)垃圾回收機(jī)制(必看篇)

    下面小編就為大家?guī)硪黄仙U凧ava虛擬機(jī)垃圾回收機(jī)制(必看篇)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-08-08
  • 基于JavaSwing+mysql開發(fā)一個(gè)學(xué)生社團(tuán)管理系統(tǒng)設(shè)計(jì)和實(shí)現(xiàn)

    基于JavaSwing+mysql開發(fā)一個(gè)學(xué)生社團(tuán)管理系統(tǒng)設(shè)計(jì)和實(shí)現(xiàn)

    項(xiàng)目使用Java swing+mysql開發(fā),可實(shí)現(xiàn)基礎(chǔ)數(shù)據(jù)維護(hù)、用戶登錄注冊、社團(tuán)信息列表查看、社團(tuán)信息添加、社團(tuán)信息修改、社團(tuán)信息刪除以及退出注銷等功能、界面設(shè)計(jì)比較簡單易學(xué)、適合作為Java課設(shè)設(shè)計(jì)以及學(xué)習(xí)技術(shù)使用,需要的朋友參考下吧
    2021-08-08

最新評論