牛客java面试题总结版(三)
13.概括的解釋下線程的幾種可用狀態。
官方版:
(一). 等待阻塞:運行( running )的線程執行 o . wait ()方法, JVM 會把該線程放 入等待隊列( waitting queue )中。
(二). 同步阻塞:運行( running )的線程在獲取對象的同步鎖時,若該同步鎖 被別的線程占用,則 JVM 會把該線程放入鎖池( lock pool )中。
(三). 其他阻塞: 運行( running )的線程執行 Thread . sleep ( long ms )或 t . join ()方法,或者發出了 I / O 請求時, JVM 會把該線程置為阻塞狀態。 當 sleep ()狀態超時、 join ()等待線程終止或者超時、或者 I / O 處理完畢時,線程重新轉入可運行( runnable )狀態。
大神版:鏈接:https://www.nowcoder.com/questionTerminal/f665a4c853b841339e7181a0fdbacfa8
來源:牛客網
操作系統線程的5種狀態:
1.新建狀態:
線程創建但沒有啟動
2.就緒狀態:
線程處于可運行的狀態,當線程獲得CPU的時間片后會被執行,時間片耗盡或主動放棄當次時間片(yield方法)時再次進入就緒狀態。
3.運行狀態:
線程得到時間片被CPU執行
4.阻塞狀態:
線程放棄CPU的時間片(一直到某個條件達成),主動進入阻塞的狀態。
同步阻塞:線程由于嘗試獲得對象的同步鎖但無法取得時,進入鎖池,等待其他線程釋放該對象的鎖。
等待阻塞:線程主動放棄對對象上的鎖的占用,進入等待對象通知的隊列。指wait方法
其他阻塞:線程主動進入休眠狀態,等待條件達成。指sleep、join方法或I/O請求。
5.終止狀態:
線程任務結束或異常退出
Java線程定義的6種狀態:
1.新建狀態NEW:
線程創建,但沒有啟動
2.可運行狀態(就緒狀態)RUNNABLE: 代表線程正在運行或者不處于阻塞、等待狀態的可以被運行的狀態。線程創建后或脫離阻塞、等待狀態后進入可運行狀態。
3.阻塞狀態BLOCKED:
代表線程嘗試獲得一個鎖時無法對鎖占用,進入阻塞狀態;當該線程能夠獲得鎖時脫離阻塞狀態。
4.等待狀態WAITING:
等待線程主動進入等待條件達成的狀態,可以使用join、wait、sleep方法。
5.計時等待狀態TIMED_WAITING:
等待狀態添加計時器,當等待條件達成或計時器耗盡時脫離等待狀態。
6.中斷狀態(終止狀態)TERMINATED:
線程任務結束或手動設置中斷標記
14.同步方法和同步代碼塊的區別是什么?
官方版:區別:
同步方法默認用this或者當前類class對象作為鎖;
同步代碼塊可以選擇以什么來加鎖,比同步方法要更細顆粒度,我們可以選擇只同步會發生同步問題的部分代碼而不是整個方法;
同步方法使用關鍵字 synchronized修飾方法,而同步代碼塊主要是修飾需要進行同步的代碼,用 synchronized(object){代碼內容}進行修飾;
15.在監視器(Monitor)內部,是如何做線程同步的?程序應該做哪種級別的同步?
官方版:監視器和鎖在Java虛擬機中是一塊使用的。監視器監視一塊同步代碼塊,確保一次只有一個線程執行同步代碼塊。每一個監視器都和一個對象引用相關聯。線程在獲取鎖之前不允許執行同步代碼。
大神版:
https://www.nowcoder.com/questionTerminal/26fc16a2a85e49a5bd5fc2b5759dbbc2
JVM基于進入和退出Monitor對象來實現方法同步和代碼塊同步,但兩者的實現細節不一樣。本質都是對一個對象的監視器(monitor)進行獲取,而這個獲取過程是排他的,也就是同一時刻只能有一個線程獲取到由synchronized所保護對象的監視器
代碼塊同步是使用monitorenter和monitorexit指令實現的。monitorenter指令是在編譯后插入到同步代碼塊的開始位置,而monitorexit是插入到方法結束處和異常處,JVM要保證每個monitorenter必須有對應的monitorexit與之配對。任何對象都有一個monitor與之關聯,當且一個monitor被持有后,它將處于鎖定狀態。線程執行到monitorenter指令時,將會嘗試獲取對象所對應的monitor的所有權,即嘗試獲得對象的鎖。
16.什么是死鎖(deadlock)?
官方版:所謂死鎖是指多個進程因競爭資源而造成的一種僵局(互相等待),若無外力作用,這些進程都將無法向前推進。死鎖產生的4個必要條件:
互斥條件:進程要求對所分配的資源(如打印機)進行排他性控制,即在一段時間內某 資源僅為一個進程所占有。此時若有其他進程請求該資源,則請求進程只能等待。
不剝奪條件:進程所獲得的資源在未使用完畢之前,不能被其他進程強行奪走,即只能 由獲得該資源的進程自己來釋放(只能是主動釋放)。
請求和保持條件:進程已經保持了至少一個資源,但又提出了新的資源請求,而該資源 已被其他進程占有,此時請求進程被阻塞,但對自己已獲得的資源保持不放。
循環等待條件:存在一種進程資源的循環等待鏈,鏈中每一個進程已獲得的資源同時被 鏈中下一個進程所請求。
可能產生死鎖的情況:
(1) 因為系統資源不足。
(2) 進程運行推進順序不合適。
(3) 資源分配不當等。
如果系統資源充足,進程的資源請求都能夠得到滿足,死鎖出現的可能性就很低,否則
就會因爭奪有限的資源而陷入死鎖。其次,進程運行推進順序與速度不同,也可能產生死鎖。
如何預防與解除死鎖
理解了死鎖的原因,尤其是產生死鎖的四個必要條件,就可以最大可能地避免、預防和
解除死鎖。所以,在系統設計、進程調度等方面注意如何不讓這四個必要條件成立,如何確
定資源的合理分配算法,避免進程永久占據系統資源。此外,也要防止進程在處于等待狀態
的情況下占用資源。因此,對資源的分配要給予合理的規劃。
17.如何確保N個線程可以訪問N個資源同時又不導致死鎖?
官方版:
使用多線程的時候,一種非常簡單的避免死鎖的方式就是:指定獲取鎖的順序,并強制線程按照指定的順序獲取鎖。因此,如果所有的線程都是以同樣的順序加鎖和釋放鎖,就不會出現死鎖了。
總結
以上是生活随笔為你收集整理的牛客java面试题总结版(三)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 牛客java面试题总结版(二)
- 下一篇: Map,HashMap,TreeMap