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