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