面試不慌!Java多線程面試題分享,吊打面試官你也可以!

1. volatile關(guān)鍵字在Java中有什么作用?

volatile是一個(gè)特殊的修飾符,只有成員變量才能使用它。

在Java并發(fā)程序缺少同步類的情況下,多線程對(duì)成員變量的操作對(duì)其它線程是透明的。

volatile變量可以保證下一個(gè)讀取操作會(huì)在前一個(gè)寫操作之后發(fā)生。

2. volatile 變量和 atomic 變量有什么不同?

首先,volatile 變量和 atomic 變量看起來(lái)很像,但功能卻不一樣。

Volatile變量可以確保先行關(guān)系,即寫操作會(huì)發(fā)生在后續(xù)的讀操作之前, 但它并不能保證原子性。例如用volatile修飾count變量那么 count++ 操作就不是原子性的。

而AtomicInteger類提供的atomic方法可以讓這種操作具有原子性如getAndIncrement()方法會(huì)原子性的進(jìn)行增量操作把當(dāng)前值加一,其它數(shù)據(jù)類型和引用變量也可以進(jìn)行相似操作。

3. Java中的同步集合與并發(fā)集合有什么區(qū)別?

同步集合與并發(fā)集合都為多線程和并發(fā)提供了合適的線程安全的集合,不過(guò)并發(fā)集合的可擴(kuò)展性更高。

Java5介紹了并發(fā)集合像ConcurrentHashMap,不僅提供線程安全還用鎖分離和內(nèi)部分區(qū)等現(xiàn)代技術(shù)提高了可擴(kuò)展性。

4. Vector是一個(gè)線程安全類嗎?

Vector 是用同步方法來(lái)實(shí)現(xiàn)線程安全的

5. ReadWriteLock是什么?

一般而言,讀寫鎖是用來(lái)提升并發(fā)程序性能的鎖分離技術(shù)的成果。

Java中的ReadWriteLock是Java 5 中新增的一個(gè)接口,一個(gè)ReadWriteLock維護(hù)一對(duì)關(guān)聯(lián)的鎖,一個(gè)用于只讀操作一個(gè)用于寫。在沒(méi)有寫線程的情況下一個(gè)讀鎖可能會(huì)同時(shí)被多個(gè)讀線程持有。寫鎖是獨(dú)占的,你可以使用JDK中的ReentrantReadWriteLock來(lái)實(shí)現(xiàn)這個(gè)規(guī)則,它最多支持65535個(gè)寫鎖和65535個(gè)讀鎖。

6. 什么是FutureTask?

在Java并發(fā)程序中FutureTask表示一個(gè)可以取消的異步運(yùn)算。

它有啟動(dòng)和取消運(yùn)算、查詢運(yùn)算是否完成和取回運(yùn)算結(jié)果等方法。只有當(dāng)運(yùn)算完成的時(shí)候結(jié)果才能取回,如果運(yùn)算尚未完成get方法將會(huì)阻塞。一個(gè)FutureTask對(duì)象可以對(duì)調(diào)用了Callable和Runnable的對(duì)象進(jìn)行包裝,由于FutureTask也是調(diào)用了Runnable接口所以它可以提交給Executor來(lái)執(zhí)行。

7. 什么是ThreadLocal變量?

ThreadLocal是Java里一種特殊的變量。

每個(gè)線程都有一個(gè)ThreadLocal就是每個(gè)線程都擁有了自己獨(dú)立的一個(gè)變量,競(jìng)爭(zhēng)條件被徹底消除了。它是為創(chuàng)建代價(jià)高昂的對(duì)象獲取線程安全的好方法,比如你可以用ThreadLocal讓SimpleDateFormat變成線程安全的,因?yàn)槟莻€(gè)類創(chuàng)建代價(jià)高昂且每次調(diào)用都需要?jiǎng)?chuàng)建不同的實(shí)例所以不值得在局部范圍使用它,如果為每個(gè)線程提供一個(gè)自己獨(dú)有的變量拷貝,將大大提高效率。

首先,通過(guò)復(fù)用減少了代價(jià)高昂的對(duì)象的創(chuàng)建個(gè)數(shù)。 其次,你在沒(méi)有使用高代價(jià)的同步或者不變性的情況下獲得了線程安全。

線程局部變量的另一個(gè)不錯(cuò)的例子是ThreadLocalRandom類,它在多線程環(huán)境中減少了創(chuàng)建代價(jià)高昂的Random對(duì)象的個(gè)數(shù)。

8. 什么是Java線程轉(zhuǎn)儲(chǔ)(Thread Dump),如何得到它?

線程轉(zhuǎn)儲(chǔ)是一個(gè)JVM活動(dòng)線程的列表,它對(duì)于分析系統(tǒng)瓶頸和死鎖非常有用。

有很多方法可以獲取線程轉(zhuǎn)儲(chǔ)——使用Profiler,Kill-3命令,jstack工具等等。有的更喜歡jstack工具,因?yàn)樗菀资褂貌⑶沂荍DK自帶的。由于它是一個(gè)基于終端的工具,所以可以編寫一些腳本去定時(shí)的產(chǎn)生線程轉(zhuǎn)儲(chǔ)以待分析。

9. 如果你提交任務(wù)時(shí),線程池隊(duì)列已滿。會(huì)時(shí)發(fā)會(huì)生什么?

如果你使用的LinkedBlockingQueue,也就是無(wú)界隊(duì)列的話,沒(méi)關(guān)系,繼續(xù)添加任務(wù)到阻塞隊(duì)列中等待執(zhí)行,因?yàn)長(zhǎng)inkedBlockingQueue可以近乎認(rèn)為是一個(gè)無(wú)窮大的隊(duì)列,可以無(wú)限存放任務(wù);

如果你使用的是有界隊(duì)列比方說(shuō)ArrayBlockingQueue的話,任務(wù)首先會(huì)被添加到ArrayBlockingQueue中,ArrayBlockingQueue滿了,則會(huì)使用拒絕策略RejectedExecutionHandler處理滿了的任務(wù),默認(rèn)是AbortPolicy。

10. 線程之間是如何通信的?

當(dāng)線程間是可以共享資源時(shí),線程間通信是協(xié)調(diào)它們的重要的手段。

Object類中wait()notify()notifyAll()方法可以用于線程間通信關(guān)于資源的鎖的狀態(tài)。

11. 怎么檢測(cè)一個(gè)線程是否持有對(duì)象監(jiān)視器

Thread類提供了一個(gè)holdsLock(Object obj)方法,當(dāng)且僅當(dāng)對(duì)象obj的監(jiān)視器被某條線程持有的時(shí)候,才會(huì)返回true.注意這是一個(gè)static方法,這意味著"某條線程"指的是當(dāng)前線程。

12. 什么是死鎖(Deadlock)?

死鎖是指兩個(gè)或兩個(gè)以上的進(jìn)程在執(zhí)行過(guò)程中,因爭(zhēng)奪資源而造成的一種互相等待的現(xiàn)象,若無(wú)外力作用,它們都將無(wú)法推進(jìn)下去。

13. 鎖的分類

  • 自旋鎖
  • 自旋鎖的其他種類
  • 阻塞鎖
  • 可重入鎖
  • 讀寫鎖
  • 互斥鎖
  • 悲觀鎖
  • 樂(lè)觀鎖
  • 公平鎖
  • 非公平鎖
  • 偏向鎖
  • 對(duì)象鎖
  • 線程鎖
  • 鎖粗化
  • 輕量級(jí)鎖
  • 鎖消除
  • 鎖膨脹
  • 信號(hào)量

14. 死鎖發(fā)生的幾個(gè)條件是什么

  • 因?yàn)橄到y(tǒng)資源不足。
  • 進(jìn)程運(yùn)行推進(jìn)的順序不合適。
  • 資源分配不當(dāng)。

15. 實(shí)現(xiàn)一個(gè)死鎖?

產(chǎn)生死鎖的四個(gè)必要條件:

  • 互斥條件:所謂互斥就是進(jìn)程在某一時(shí)間內(nèi)獨(dú)占資源。
  • 請(qǐng)求與保持條件:一個(gè)進(jìn)程因請(qǐng)求資源而阻塞時(shí),對(duì)已獲得的資源保持不放。
  • 不剝奪條件:進(jìn)程已獲得資源,在末使用完之前,不能強(qiáng)行剝奪。
  • 循環(huán)等待條件:若干進(jìn)程之間形成一種頭尾相接的循環(huán)等待資源關(guān)系。

16. 如何避免死鎖?

打破產(chǎn)生死鎖的四個(gè)必要條件中的一個(gè)或幾個(gè),保證系統(tǒng)不會(huì)進(jìn)入死鎖狀態(tài)。

  1. 打破互斥條件。即允許進(jìn)程同時(shí)訪問(wèn)某些資源。但是,有的資源是不允許被同時(shí)訪問(wèn)的,像打印機(jī)等等,這是由資源本身的屬性所決定的。所以,這種辦法并無(wú)實(shí)用價(jià)值。
  2. 打破不可搶占條件。即允許進(jìn)程強(qiáng)行從占有者那里奪取某些資源。就是說(shuō),當(dāng)一個(gè)進(jìn)程已占有了某些資源,它又申請(qǐng)新的資源,但不能立即被滿足時(shí),它必須釋放所占有的全部資源,以后再重新申請(qǐng)。它所釋放的資源可以分配給其它進(jìn)程。這就相當(dāng)于該進(jìn)程占有的資源被隱蔽地強(qiáng)占了。這種預(yù)防死鎖的方法實(shí)現(xiàn)起來(lái)困難,會(huì)降低系統(tǒng)性能。
  3. 打破占有且申請(qǐng)條件??梢詫?shí)行資源預(yù)先分配策略。即進(jìn)程在運(yùn)行前一次性地向系統(tǒng)申請(qǐng)它所需要的全部資源。如果某個(gè)進(jìn)程所需的全部資源得不到滿足,則不分配任何資源,此進(jìn)程暫不運(yùn)行。只有當(dāng)系統(tǒng)能夠滿足當(dāng)前進(jìn)程的全部資源需求時(shí),才一次性地將所申請(qǐng)的資源全部分配給該進(jìn)程。由于運(yùn)行的進(jìn)程已占有了它所需的全部資源,所以不會(huì)發(fā)生占有資源又申請(qǐng)資源的現(xiàn)象,因此不會(huì)發(fā)生死鎖。 四.打破循環(huán)等待條件,實(shí)行資源有序分配策略。采用這種策略,即把資源事先分類編號(hào),按號(hào)分配,使進(jìn)程在申請(qǐng),占用資源時(shí)不會(huì)形成環(huán)路。所有進(jìn)程對(duì)資源的請(qǐng)求必須嚴(yán)格按資源序號(hào)遞增的順序提出。進(jìn)程占用了小號(hào)資源,才能申請(qǐng)大號(hào)資源,就不會(huì)產(chǎn)生環(huán)路,從而預(yù)防了死鎖。

17. Java中活鎖和死鎖有什么區(qū)別?

活鎖和死鎖類似,不同之處在于處于活鎖的線程或進(jìn)程的狀態(tài)是不斷改變的,活鎖可以認(rèn)為是一種特殊的饑餓。

一個(gè)現(xiàn)實(shí)的活鎖例子是兩個(gè)人在狹小的走廊碰到,兩個(gè)人都試著避讓對(duì)方好讓彼此通過(guò),但是因?yàn)楸茏尩姆较蚨家粯訉?dǎo)致最后誰(shuí)都不能通過(guò)走廊。

簡(jiǎn)單的說(shuō)就是,活鎖和死鎖的主要區(qū)別是前者進(jìn)程的狀態(tài)可以改變但是卻不能繼續(xù)執(zhí)行。

18. 死鎖與饑餓的區(qū)別?

饑餓是指系統(tǒng)不能保證某個(gè)進(jìn)程的等待時(shí)間上界,從而使該進(jìn)程長(zhǎng)時(shí)間等待,當(dāng)?shù)却龝r(shí)間給進(jìn)程推進(jìn)和響應(yīng)帶來(lái)明顯影響時(shí),稱發(fā)生了進(jìn)程饑餓。當(dāng)饑餓到一定程度的進(jìn)程所賦予的任務(wù)即使完成也不再具有實(shí)際意義時(shí)稱該進(jìn)程被餓死。

死鎖是指在多道程序系統(tǒng)中,一組進(jìn)程中的每一個(gè)進(jìn)程都無(wú)限期等待被該組進(jìn)程中的另一個(gè)進(jìn)程所占有且永遠(yuǎn)不會(huì)釋放的資源。

相同點(diǎn):二者都是由于競(jìng)爭(zhēng)資源而引起的。

不同點(diǎn)

  • 從進(jìn)程狀態(tài)考慮,死鎖進(jìn)程都處于等待狀態(tài),忙等待(處于運(yùn)行或就緒狀態(tài))的進(jìn)程并非處于等待狀態(tài),但卻可能被餓死;
  • 死鎖進(jìn)程等待永遠(yuǎn)不會(huì)被釋放的資源,餓死進(jìn)程等待會(huì)被釋放但卻不會(huì)分配給自己的資源,表現(xiàn)為等待時(shí)限沒(méi)有上界(排隊(duì)等待或忙式等待);
  • 死鎖一定發(fā)生了循環(huán)等待,而餓死則不然。這也表明通過(guò)資源分配圖可以檢測(cè)死鎖存在與否,但卻不能檢測(cè)是否有進(jìn)程餓死;
  • 死鎖一定涉及多個(gè)進(jìn)程,而饑餓或被餓死的進(jìn)程可能只有一個(gè)。
  • 在饑餓的情形下,系統(tǒng)中有至少一個(gè)進(jìn)程能正常運(yùn)行,只是饑餓進(jìn)程得不到執(zhí)行機(jī)會(huì)。而死鎖則可能會(huì)最終使整個(gè)系統(tǒng)陷入死鎖并崩潰。

19. 什么是樂(lè)觀鎖和悲觀鎖

悲觀鎖:假定會(huì)發(fā)生并發(fā)沖突,屏蔽一切可能違反數(shù)據(jù)完整性的操作。 樂(lè)觀鎖:假設(shè)不會(huì)發(fā)生并發(fā)沖突,只在提交操作時(shí)檢查是否違反數(shù)據(jù)完整性。樂(lè)觀鎖不能解決臟讀的問(wèn)題。

20. 什么是對(duì)象鎖?

對(duì)象鎖是指Java為臨界區(qū)synchronized(Object)語(yǔ)句指定的對(duì)象進(jìn)行加鎖,對(duì)象鎖是獨(dú)占排他鎖。

對(duì)于對(duì)象鎖,是針對(duì)一個(gè)對(duì)象的,它只在該對(duì)象的某個(gè)內(nèi)存位置聲明一個(gè)標(biāo)志位標(biāo)識(shí)該對(duì)象是否擁有鎖,所以它只會(huì)鎖住當(dāng)前的對(duì)象。一般一個(gè)對(duì)象鎖是對(duì)一個(gè)非靜態(tài)成員變量進(jìn)行syncronized修飾,或者對(duì)一個(gè)非靜態(tài)方法進(jìn)行syncronized修飾。對(duì)于對(duì)象鎖,不同對(duì)象訪問(wèn)同一個(gè)被syncronized修飾的方法的時(shí)候不會(huì)阻塞住。

21. 怎么檢測(cè)一個(gè)線程是否擁有鎖?

在java.lang.Thread中有一個(gè)方法叫holdsLock(),它返回true如果當(dāng)且僅當(dāng)當(dāng)前線程擁有某個(gè)具體對(duì)象的鎖。

22. Java中synchronized 和 ReentrantLock 有什么不同?

Java在過(guò)去很長(zhǎng)一段時(shí)間只能通過(guò)synchronized關(guān)鍵字來(lái)實(shí)現(xiàn)互斥,它有一些缺點(diǎn)。比如你不能擴(kuò)展鎖之外的方法或者塊邊界,嘗試獲取鎖時(shí)不能中途取消等。Java 5 通過(guò)Lock接口提供了更復(fù)雜的控制來(lái)解決這些問(wèn)題。 ReentrantLock 類實(shí)現(xiàn)了 Lock,它擁有與 synchronized 相同的并發(fā)性和內(nèi)存語(yǔ)義且它還具有可擴(kuò)展性。

23. 可重入鎖的含義

可重入鎖,也叫做遞歸鎖,指的是同一線程 外層函數(shù)獲得鎖之后 ,內(nèi)層遞歸函數(shù)仍然有獲取該鎖的代碼,但不受影響。

在Java環(huán)境下 ReentrantLock 和synchronized 都是可重入鎖

24. 什么是CAS

CAS,全稱為Compare and Swap,即比較-替換。假設(shè)有三個(gè)操作數(shù):內(nèi)存值V、舊的預(yù)期值A(chǔ)、要修改的值B,當(dāng)且僅當(dāng)預(yù)期值A(chǔ)和內(nèi)存值V相同時(shí),才會(huì)將內(nèi)存值修改為B并返回true,否則什么都不做并返回false。當(dāng)然CAS一定要volatile變量配合,這樣才能保證每次拿到的變量是主內(nèi)存中最新的那個(gè)值,否則舊的預(yù)期值A(chǔ)對(duì)某條線程來(lái)說(shuō),永遠(yuǎn)是一個(gè)不會(huì)變的值A(chǔ),只要某次CAS操作失敗,永遠(yuǎn)都不可能成功

# 鏈接 Java程序員福利"常用資料分享"

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Java SE 基礎(chǔ): 封裝、繼承、多態(tài) 封裝: 概念:就是把對(duì)象的屬性和操作(或服務(wù))結(jié)合為一個(gè)獨(dú)立的整體,并盡...
    Jayden_Cao閱讀 2,234評(píng)論 0 8
  • Java-Review-Note——4.多線程 標(biāo)簽: JavaStudy PS:本來(lái)是分開(kāi)三篇的,后來(lái)想想還是整...
    coder_pig閱讀 1,760評(píng)論 2 17
  • 不管你是新程序員還是老手,你一定在面試中遇到過(guò)有關(guān)線程的問(wèn)題。Java語(yǔ)言一個(gè)重要的特點(diǎn)就是內(nèi)置了對(duì)并發(fā)的支持,讓...
    堯淳閱讀 1,663評(píng)論 0 25
  • 相關(guān)概念 面向?qū)ο蟮娜齻€(gè)特征 封裝,繼承,多態(tài).這個(gè)應(yīng)該是人人皆知.有時(shí)候也會(huì)加上抽象. 多態(tài)的好處 允許不同類對(duì)...
    東經(jīng)315度閱讀 2,191評(píng)論 0 8
  • 根據(jù)熱祭的理論,整個(gè)宇宙的演化方向是從有序到無(wú)序,最終終點(diǎn)則是宇宙處于完全混亂的熱平衡狀態(tài),也就是熵最大。而生命卻...
    RawHeart心然閱讀 801評(píng)論 0 1

友情鏈接更多精彩內(nèi)容