乙個執行緒OOM之後,程序會崩潰麼

2021-09-25 15:02:29 字數 1839 閱讀 6438

偶然間看到乙個問題,乙個執行緒oom之後,程序裡面的其他執行緒還能執行嗎?看了其他部落格裡面都說可以執行,但是按照專案上的經驗,我們的專案是部署在tomcat中執行,如果發生oom,這個時候傳送請求是不會有回應的!所以本文打算分析一下某個執行緒記憶體溢位是,程序中的其他執行緒到低能否正常執行。

先說下個人測試得出來的結論:

outofmemoryerror是一種錯誤,它是 jvm 的一種自我防禦機制,用於防止整個應用程式崩潰,這個時候執行緒會被kill掉,然後丟擲outofmemory異常資訊。因為棧上的空間是執行緒私有的,所以執行緒被kill掉之後,棧上的空間就被釋放了,但是堆空間是共享的,被kill掉的執行緒中的物件可能被該執行緒之外的其他執行緒引用,這個時候這部分物件就沒有辦法被gc掉,其他執行緒如果此時需要申請資源但是又資源又不足,那麼此時其他執行緒就不能執行。

為什麼tomcat記憶體溢位之後其他請求也無法響應了呢?個人猜測是:outofmemory執行緒所持有的大物件被其他執行緒引用了,所以gc的時候gc root鏈還是可達的,同時其他執行緒也要使用記憶體,此時記憶體不夠了,所以其他執行緒也用不了了。

要明確的一點是:執行緒被kill和記憶體**是兩件完全不同的事情。

個人測試**如下:

public static void main(string args)  catch (interruptedexception e) }}

});thread thread2 = new thread(() -> catch (interruptedexception e)

}});

//這個執行緒也在申請資源

thread thread3 = new thread(new runnable() catch (interruptedexception e) }}

});thread1.start();

thread2.start();

thread3.start();

while (true) catch (interruptedexception e)

system.gc();}}

thread1和thread3都在申請記憶體,thread2只是輸出資訊。

開啟thread1和thread2,不顯示呼叫system.gc(),變數為執行緒是有或者被主線程持有

執行緒會被kill,但是不管變數是否是執行緒私有的,記憶體都不會被**,因為不滿足gc條件。圖示如下:

2.開始thread1和thread2,顯示呼叫system.gc(),變數如果為執行緒私有的話會被**,如果還被其他執行緒持有,那麼這部分空間就不會被**

引用還被其他執行緒持有的情況:

物件為執行緒私有的情況:

可以看出,如果物件的引用被其他執行緒持有,物件是不會被**的!

3.三個執行緒都開啟,不顯示呼叫system.gc(),物件未執行緒私有

thread1和thread3會先後發生執行緒溢位,thread1在先溢位之後,物件沒有被**,但是thread3也在持續申請記憶體。所以thread3申請不到記憶體時,jvm會進行一次full gc,**thread1占用的記憶體好分配給thread3。thread3一直申請記憶體直到記憶體溢位。

乙個程序可以建立多少執行緒

理論上,乙個程序可用虛擬空間是2g,預設情況下,執行緒的棧的大小是1mb,所以理論上最多只能建立2048個執行緒。如果要建立多於2048的話,必須修改編譯器的設定。include include includehandle hprocess handle hthread dword winapi a...

記錄乙個linux程序不執行不崩潰的問題

程式需求是不斷連線資料庫,並斷開,再連線,反覆迴圈。於是寫了個死迴圈。死迴圈總是鬼畜的 而資料庫的連線由於某種鬼畜的原因,不能用jdbc,odbc等api,只能使用linux命令連線,不做深究。然後本菜雞寫了乙個如下的程式。define thread num 101 void getprocessi...

乙個程序最多能包含多少執行緒

小watch水平有限,希望大家多多指正文中的錯誤,共同進步 最近在學習os的多執行緒課程,第乙個實驗室關於windows的多執行緒,用mfc實現。實驗蠻簡單的,但是,我不由想到了,乙個程序最多能包含多少個執行緒。在網上查了查,貌似也沒找到多少這方面的資料。大部分都是關於伺服器多執行緒鏈結sever的...