多線程面試題


同步機制應該遵循的基本准則 

· 空閑讓進:當無進程處於臨界區時,表明臨界資源處於空閑狀態,允許一個請求進入臨界區的進程立即進入臨界區,以有效利用臨界資源

 · 忙則等待:當已有進程處於臨界區時,表明臨界資源正在被訪問,因而其他試圖進入臨界區的進程必須等待,以保證對臨界資源的互斥訪問

 · 有限等待:對要求訪問臨界資源的進程,應保證在有限時間內能進入自己的臨界區,以免陷入“死等”狀態

 · 讓權等待:當進程不能進入自己的臨界區時,應立即釋放處理機,以免進程陷入“忙等”狀態

 

產生死鎖的原因主要是: 
(1) 因為系統資源不足。 
(2) 進程運行推進的順序不合適。 
(3) 資源分配不當等。
 
產生死鎖的四個必要條件: 
(1) 互斥條件:一個資源每次只能被一個進程使用。 
(2) 請求與保持條件:一個進程因請求資源而阻塞時,對已獲得的資源保持不放。 
(3) 不剝奪條件:進程已獲得的資源,在末使用完之前,不能強行剝奪。 
(4) 循環等待條件:若干進程之間形成一種頭尾相接的循環等待資源關系。
 
共享內存並未提供同步機制,當某一個進程對共享內存提供寫操作時,並未自動的阻止另一個進程對它進行讀取;
共享內存:就是允許多個進程訪問同一內存空間,進程間傳遞和共享數據非常有效
信號量:為了防止多個進程訪問共享資源而造成沖突,設置臨界區域每次只讓一個進程訪問,信號量提供了這樣一種機制,用來控制對臨界區域的訪問
 
 
進程間通信的方式有管道(pipe)、共享存儲器系統、消息傳遞系統(message queue)以及信號量。而mutex是互斥鎖,在鎖機制中通過原語保證資源狀態的檢查和修改作為一個整體來執行,以保證共享數據操作的完整性,並不能在兩個進程間傳遞消息。網絡上的兩個程序通過一個雙向的通信連接實現數據的交換,這個連接的一端稱為一個socket,也就是說socket也是兩個進程間的通信方式。
 
 
進程是資源分配和擁有的單位,同一個進程內的線程共享進程的資源
線程作為調度和分配的基本單位,進程作為擁有資源的基本單位
線程的划分尺度小於進程,使得多線程程序的並發性高
在同一進程中的各個線程,才可以共享該進程所擁有的資源
 
多線程調用時要進行保護時,主要是針對全局變量和靜態變量的,函數內的局部變量不會受到影響。
這里i是全局變量,j是局部靜態變量,所以 要進行保護。
 
——————————————————————————————————————————————————————————————

1、線程與進程的區別?

進程是操作系統分配資源的最小單元,線程是操作系統調度的最小單元。

一個程序至少有一個進程,一個進程至少有一個線程。

 

 

2、什么是多線程中的上下文切換?

多線程會共同使用一組計算機上的CPU,而線程數大於給程序分配的CPU數量時,為了讓各個線程都有執行的機會,就需要輪轉使用CPU。不同的線程切換使用CPU發生的切換數據等就是上下文切換。

 

 

3、多線程同步和互斥有幾種實現方法,都是什么?

線程同步是指線程之間所具有的一種制約關系,一個線程的執行依賴另一個線程的消息,當它沒有得到另一個線程的消息時應等待,直到消息到達時才被喚醒。

線程互斥是指對於共享的進程系統資源,在各單個線程訪問時的排它性。當有若干個線程都要使用某一共享資源時,任何時刻最多只允許一個線程去使用,其它要使用該資源的線程必須等待,直到占用資源者釋放該資源。線程互斥可以看成是一種特殊的線程同步。

線程間的同步方法大體可分為兩類:用戶模式和內核模式。顧名思義,內核模式就是指利用系統內核對象的單一性來進行同步,使用時需要切換內核態與用戶態,而用戶模式就是不需要切換到內核態,只在用戶態完成操作。

用戶模式下的方法有:原子操作(例如一個單一的全局變量),臨界區。內核模式下的方法有:事件,信號量,互斥量。

 

21、java如何實現多線程之間的通訊和協作?

中斷和共享變量

 

23、volatile有什么用?能否用一句話說明下volatile的應用場景?

volatile保證內存可見性和禁止指令重排。

volatile用於多線程環境下的單次操作(單次讀或者單次寫)。

 

 

25、在java中wait和sleep方法的不同?

最大的不同是在等待時wait會釋放鎖,而sleep一直持有鎖。Wait通常被用於線程間交互,sleep通常被用於暫停執行。

直接了解的深入一點吧:

 

 

 

在Java中線程的狀態一共被分成6種:

初始態:NEW

創建一個Thread對象,但還未調用start()啟動線程時,線程處於初始態。

運行態:RUNNABLE

在Java中,運行態包括就緒態和運行態。

就緒態該狀態下的線程已經獲得執行所需的所有資源,只要CPU分配執行權就能運行。所有就緒態的線程存放在就緒隊列中。

運行態獲得CPU執行權,正在執行的線程。由於一個CPU同一時刻只能執行一條線程,因此每個CPU每個時刻只有一條運行態的線程。

阻塞態

當一條正在執行的線程請求某一資源失敗時,就會進入阻塞態。而在Java中,阻塞態專指請求鎖失敗時進入的狀態。由一個阻塞隊列存放所有阻塞態的線程。處於阻塞態的線程會不斷請求資源,一旦請求成功,就會進入就緒隊列,等待執行。PS:鎖、IO、Socket等都資源。

等待態

當前線程中調用wait、join、park函數時,當前線程就會進入等待態。也有一個等待隊列存放所有等待態的線程。線程處於等待態表示它需要等待其他線程的指示才能繼續運行。進入等待態的線程會釋放CPU執行權,並釋放資源(如:鎖)

超時等待態

當運行中的線程調用sleep(time)、wait、join、parkNanos、parkUntil時,就會進入該狀態;它和等待態一樣,並不是因為請求不到資源,而是主動進入,並且進入后需要其他線程喚醒;進入該狀態后釋放CPU執行權 和 占有的資源。與等待態的區別:到了超時時間后自動進入阻塞隊列,開始競爭鎖。

終止態

線程執行結束后的狀態。

注意:

wait()方法會釋放CPU執行權 和 占有的鎖。

sleep(long)方法僅釋放CPU使用權,鎖仍然占用;線程被放入超時等待隊列,與yield相比,它會使線程較長時間得不到運行。

yield()方法僅釋放CPU執行權,鎖仍然占用,線程會被放入就緒隊列,會在短時間內再次執行。

wait和notify必須配套使用,即必須使用同一把鎖調用;

wait和notify必須放在一個同步塊中調用wait和notify的對象必須是他們所處同步塊的鎖對象。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM