多線程技術(shù)在互聯(lián)網(wǎng)技術(shù)方面使用如此廣泛,幾乎所有的后端技術(shù)面試官都要在并發(fā)編程的使用和原理方面對(duì)小伙伴們進(jìn)行各種刁難。作為一名在互聯(lián)網(wǎng)技術(shù)行業(yè)打擊過(guò)成百上千名【請(qǐng)?jiān)试S我夸張一下】的資深技術(shù)面試官,看過(guò)了無(wú)數(shù)落寞的身影失望的離開(kāi),略感愧疚,故獻(xiàn)上此文,希望各位讀者以后面試勢(shì)如破竹,永無(wú)失敗!
覺(jué)得文章對(duì)你有幫助的話,可以點(diǎn)贊關(guān)注一下,給作者一點(diǎn)小鼓勵(lì)。
什么是線程?
線程是操作系統(tǒng)能夠進(jìn)行運(yùn)算調(diào)度的最小單位,它被包含在進(jìn)程之中,是進(jìn)程中的實(shí)際運(yùn)作單位,可以使用多線程對(duì)進(jìn)行運(yùn)算提速。
比如,如果一個(gè)線程完成一個(gè)任務(wù)要100毫秒,那么用十個(gè)線程完成改任務(wù)只需10毫秒
什么是多線程??jī)?yōu)缺點(diǎn)?
什么是多線程?
多線程:是指從軟件或者硬件上實(shí)現(xiàn)多個(gè)線程的并發(fā)技術(shù)。
多線程的好處:
使用多線程可以把程序中占據(jù)時(shí)間長(zhǎng)的任務(wù)放到后臺(tái)去處理,如圖片、視屏的下載
發(fā)揮多核處理器的優(yōu)勢(shì),并發(fā)執(zhí)行讓系統(tǒng)運(yùn)行的更快、更流暢,用戶體驗(yàn)更好
多線程的缺點(diǎn):
大量的線程降低代碼的可讀性;
更多的線程需要更多的內(nèi)存空間
當(dāng)多個(gè)線程對(duì)同一個(gè)資源出現(xiàn)爭(zhēng)奪時(shí)候要注意線程安全的問(wèn)題。
線程的五個(gè)狀態(tài)(五種狀態(tài),創(chuàng)建、就緒、運(yùn)行、阻塞和死亡)?
線程通常都有五種狀態(tài),創(chuàng)建、就緒、運(yùn)行、阻塞和死亡。
第一是創(chuàng)建狀態(tài)。在生成線程對(duì)象,并沒(méi)有調(diào)用該對(duì)象的start方法,這是線程處于創(chuàng)建狀態(tài)。
第二是就緒狀態(tài)。當(dāng)調(diào)用了線程對(duì)象的start方法之后,該線程就進(jìn)入了就緒狀態(tài),但是此時(shí)線程調(diào)度程序還沒(méi)有把該線程設(shè)置為當(dāng)前線程,此時(shí)處于就緒狀態(tài)。在線程運(yùn)行之后,從等待或者睡眠中回來(lái)之后,也會(huì)處于就緒狀態(tài)。
第三是運(yùn)行狀態(tài)。線程調(diào)度程序?qū)⑻幱诰途w狀態(tài)的線程設(shè)置為當(dāng)前線程,此時(shí)線程就進(jìn)入了運(yùn)行狀態(tài),開(kāi)始運(yùn)行run函數(shù)當(dāng)中的代碼。
第四是阻塞狀態(tài)。線程正在運(yùn)行的時(shí)候,被暫停,通常是為了等待某個(gè)時(shí)間的發(fā)生(比如說(shuō)某項(xiàng)資源就緒)之后再繼續(xù)運(yùn)行。sleep,suspend,wait等方法都可以導(dǎo)致線程阻塞。
第五是死亡狀態(tài)。如果一個(gè)線程的run方法執(zhí)行結(jié)束或者調(diào)用stop方法后,該線程就會(huì)死亡。對(duì)于已經(jīng)死亡的線程,無(wú)法再使用start方法令其進(jìn)入就緒
什么是CAS?
CAS(compare and swap)的縮寫(xiě),中文翻譯成比較并交換。
CAS 不通過(guò)JVM,直接利用java本地方 JNI(Java Native Interface為JAVA本地調(diào)用),直接調(diào)用CPU 的cmpxchg(是匯編指令)指令。
利用CPU的CAS指令,同時(shí)借助JNI來(lái)完成Java的非阻塞算法,實(shí)現(xiàn)原子操作。其它原子操作都是利用類似的特性完成的。
整個(gè)java.util.concurrent都是建立在CAS之上的,因此對(duì)于synchronized阻塞算法,J.U.C在性能上有了很大的提升。
CAS是項(xiàng)樂(lè)觀鎖技術(shù),當(dāng)多個(gè)線程嘗試使用CAS同時(shí)更新同一個(gè)變量時(shí),只有其中一個(gè)線程能更新變量的值,而其它線程都失敗,失敗的線程并不會(huì)被掛起,而是被告知這次競(jìng)爭(zhēng)中失敗,并可以再次嘗試。
CAS應(yīng)用
CAS有3個(gè)操作數(shù),內(nèi)存值V,舊的預(yù)期值A(chǔ),要修改的新值B。當(dāng)且僅當(dāng)預(yù)期值A(chǔ)和內(nèi)存值V相同時(shí),將內(nèi)存值V修改為B,否則什么都不做。
CAS優(yōu)點(diǎn)
確保對(duì)內(nèi)存的讀-改-寫(xiě)操作都是原子操作執(zhí)行
CAS缺點(diǎn)
CAS雖然很高效的解決原子操作,但是CAS仍然存在三大問(wèn)題。ABA問(wèn)題,循環(huán)時(shí)間長(zhǎng)開(kāi)銷大和只能保證一個(gè)共享變量的原子操作
什么是AQS?
AbstractQueuedSynchronizer簡(jiǎn)稱AQS,是一個(gè)用于構(gòu)建鎖和同步容器的框架。事實(shí)上concurrent包內(nèi)許多類都是基于AQS構(gòu)建,例如ReentrantLock,Semaphore,CountDownLatch,ReentrantReadWriteLock,F(xiàn)utureTask等。AQS解決了在實(shí)現(xiàn)同步容器時(shí)設(shè)計(jì)的大量細(xì)節(jié)問(wèn)題。
AQS使用一個(gè)FIFO的隊(duì)列表示排隊(duì)等待鎖的線程,隊(duì)列頭節(jié)點(diǎn)稱作“哨兵節(jié)點(diǎn)”或者“啞節(jié)點(diǎn)”,它不與任何線程關(guān)聯(lián)。其他的節(jié)點(diǎn)與等待線程關(guān)聯(lián),每個(gè)節(jié)點(diǎn)維護(hù)一個(gè)等待狀態(tài)waitStatus。
什么是樂(lè)觀鎖和悲觀鎖?
悲觀鎖
Java在JDK1.5之前都是靠synchronized關(guān)鍵字保證同步的,這種通過(guò)使用一致的鎖定協(xié)議來(lái)協(xié)調(diào)對(duì)共享狀態(tài)的訪問(wèn),可以確保無(wú)論哪個(gè)線程持有共享變量的鎖,都采用獨(dú)占的方式來(lái)訪問(wèn)這些變量。獨(dú)占鎖其實(shí)就是一種悲觀鎖,所以可以說(shuō)synchronized是悲觀鎖。
樂(lè)觀鎖
樂(lè)觀鎖( Optimistic Locking)其實(shí)是一種思想。相對(duì)悲觀鎖而言,樂(lè)觀鎖假設(shè)認(rèn)為數(shù)據(jù)一般情況下不會(huì)造成沖突,所以在數(shù)據(jù)進(jìn)行提交更新的時(shí)候,才會(huì)正式對(duì)數(shù)據(jù)的沖突與否進(jìn)行檢測(cè),如果發(fā)現(xiàn)沖突了,則讓返回用戶錯(cuò)誤的信息,讓用戶決定如何去做。
并發(fā)編程(concurrency)并行編程(parallellism)有什么區(qū)別?
并發(fā)(concurrency)和并行(parallellism)是:
解釋一:并行是指兩個(gè)或者多個(gè)事件在同一時(shí)刻發(fā)生;而并發(fā)是指兩個(gè)或多個(gè)事件在同一時(shí)間間隔發(fā)生。
解釋二:并行是在不同實(shí)體上的多個(gè)事件,并發(fā)是在同一實(shí)體上的多個(gè)事件。
解釋三:在一臺(tái)處理器上“同時(shí)”處理多個(gè)任務(wù),在多臺(tái)處理器上同時(shí)處理多個(gè)任務(wù)。如hadoop分布式集群
所以并發(fā)編程的目標(biāo)是充分的利用處理器的每一個(gè)核,以達(dá)到最高的處理性能。
想要了解更多多線程知識(shí)點(diǎn)的,可以加群650385180,多線程的學(xué)習(xí)資料以及多線程面試題匯總都在群的共享區(qū)供大家免費(fèi)下載。
怎么喚醒一個(gè)阻塞的線程?
如果線程是因?yàn)檎{(diào)用了wait()、sleep()或者join()方法而導(dǎo)致的阻塞,可以中斷線程,并且通過(guò)拋出InterruptedException來(lái)喚醒它;如果線程遇到了IO阻塞,無(wú)能為力,因?yàn)镮O是操作系統(tǒng)實(shí)現(xiàn)的,Java代碼并沒(méi)有辦法直接接觸到操作系統(tǒng)。
如何檢測(cè)死鎖?怎么預(yù)防死鎖?
所謂死鎖:是指兩個(gè)或兩個(gè)以上的進(jìn)程在執(zhí)行過(guò)程中,因爭(zhēng)奪資源而造成的一種互相等待的現(xiàn)象,若無(wú)外力作用,它們都將無(wú)法推進(jìn)下去。此時(shí)稱系統(tǒng)處于死鎖
通俗地講就是兩個(gè)或多個(gè)進(jìn)程被無(wú)限期地阻塞、相互等待的一種狀態(tài)
死鎖產(chǎn)生的原因?
1.因競(jìng)爭(zhēng)資源發(fā)生死鎖 現(xiàn)象:系統(tǒng)中供多個(gè)進(jìn)程共享的資源的數(shù)目不足以滿足全部進(jìn)程的需要時(shí),就會(huì)引起對(duì)諸資源的競(jìng)爭(zhēng)而發(fā)生死鎖現(xiàn)象
2.進(jìn)程推進(jìn)順序不當(dāng)發(fā)生死鎖
死鎖的四個(gè)必要條件:
互斥條件:進(jìn)程對(duì)所分配到的資源不允許其他進(jìn)程進(jìn)行訪問(wèn),若其他進(jìn)程訪問(wèn)該資源,只能等待,直至占有該資源的進(jìn)程使用完成后釋放該資源
請(qǐng)求和保持條件:進(jìn)程獲得一定的資源之后,又對(duì)其他資源發(fā)出請(qǐng)求,但是該資源可能被其他進(jìn)程占有,此事請(qǐng)求阻塞,但又對(duì)自己獲得的資源保持不放
不可剝奪條件:是指進(jìn)程已獲得的資源,在未完成使用之前,不可被剝奪,只能在使用完后自己釋放
環(huán)路等待條件:是指進(jìn)程發(fā)生死鎖后,若干進(jìn)程之間形成一種頭尾相接的循環(huán)等待資源關(guān)系
這四個(gè)條件是死鎖的必要條件,只要系統(tǒng)發(fā)生死鎖,這些條件必然成立,而只要上述條件之
一不滿足,就不會(huì)發(fā)生死鎖。
檢測(cè)死鎖
有兩個(gè)容器,一個(gè)用于保存線程正在請(qǐng)求的鎖,一個(gè)用于保存線程已經(jīng)持有的鎖。每次加鎖之前都會(huì)做如下檢測(cè):
檢測(cè)當(dāng)前正在請(qǐng)求的鎖是否已經(jīng)被其它線程持有,如果有,則把那些線程找出來(lái)
遍歷第一步中返回的線程,檢查自己持有的鎖是否正被其中任何一個(gè)線程請(qǐng)求,如果第二步返回真,表示出現(xiàn)了死鎖
死鎖的解除與預(yù)防:
理解了死鎖的原因,尤其是產(chǎn)生死鎖的四個(gè)必要條件,就可以最大可能地避免、預(yù)防和解除死鎖。
所以,在系統(tǒng)設(shè)計(jì)、進(jìn)程調(diào)度等方面注意如何不讓這四個(gè)必要條件成立,如何確定資源的合理分配算法,避免進(jìn)程永久占據(jù)系統(tǒng)資源。
此外,也要防止進(jìn)程在處于等待狀態(tài)的情況下占用資源。因此,對(duì)資源的分配要給予合理的規(guī)劃。
想要了解更多多線程知識(shí)點(diǎn)的,可以加群650385180,多線程的學(xué)習(xí)資料以及多線程面試題匯總都在群的共享區(qū)供大家免費(fèi)下載。
更多多線程面試題
什么是原子操作?在Java Concurrency API中有哪些原子類(atomic classes)?
什么是Executors框架?
什么是阻塞隊(duì)列?如何使用阻塞隊(duì)列來(lái)實(shí)現(xiàn)生產(chǎn)者-消費(fèi)者模型?
什么是Callable和Future?
什么是FutureTask?
什么是同步容器和并發(fā)容器的實(shí)現(xiàn)?
什么是多線程的上下文切換?
ThreadLocal的設(shè)計(jì)理念與作用?
ThreadPool(線程池)用法與優(yōu)勢(shì)?
加群:650385180獲取更多多線程知識(shí)點(diǎn)及面試題
Concurrent包里的其他東西:ArrayBlockingQueue、CountDownLatch等等。
synchronized和ReentrantLock的區(qū)別?
Semaphore有什么作用?
Java Concurrency API中的Lock接口(Lock interface)是什么?對(duì)比同步它有什么優(yōu)勢(shì)?
總結(jié)
關(guān)于Java多線程面試技術(shù)點(diǎn)的一些總結(jié)已經(jīng)寫(xiě)完了,受限于我的視野,所以可能寫(xiě)的不是很全面,大家要是有不同意見(jiàn)的,可以分享出來(lái),一起交流,要是想深入了解多線程技術(shù)知識(shí)點(diǎn)的,可以加上面的群,希望可以幫助在這個(gè)行業(yè)發(fā)展的朋友和童鞋們,在論壇博客等地方少花些時(shí)間找資料,把有限的時(shí)間,真正花在學(xué)習(xí)上。
評(píng)論
查看更多