線程崩潰是否會造成進程崩潰?

線程不是有自己單獨的堆棧與內存空間嗎?
那線程崩潰的時候進程會崩潰嗎?
順便問一下時鐘(timer)也是屬於線程吧,進程上的時鐘造成的崩潰會導致進程崩潰嗎?
其實我很好奇,我的程序進程僅僅是用來啟動線程的(線程量很多,且需要同時進行),然後就是一些時鐘了,可是有時候依舊會崩潰..


程序錯誤有很多種,有的會導致進程退出,有的不會。不知道您說的「崩潰」具體指的是什麼。

Timer有很多不同的實現,不一定是一個單獨線程。Windows的timer大多是基於timer message的,一般會和所有message handling享用一個線程。Linux的timer大多是基於signal的,signal是一個interrupt機制,會進入interrupt handler的context,嚴格說不是thread。

一般系統都會有最大線程數,嘗試開超過這個數的線程會在創建線程的時候返回錯誤。線程也一般不推薦開很多(比如上千個線程,因為電腦一般沒有那麼多核)。需要大量並行的應該考慮用event-driven的寫法或者用coroutine,懶著折騰event loop或者coroutine可以考慮用node.js或者用golang寫。

不過就算開了很多線程,跑起來一般也不會導致崩潰。一個合格的程序員這時需要做的是調試查log找到崩潰的具體原因和代碼,而不是瞎猜崩潰是哪個進程導致的。


會崩潰。線程沒有自己單獨的內存地址空間。

在一個線程中把另外一個線程的棧空間寫壞是再正常不過的事情了。這與進程有沒有自己的棧空間無關,因為無論他們有沒有自己的棧空間,都可以通過內存地址訪問到其他線程的棧空間,所以指針數據的錯誤可以導致任何同地址空間內其他線程的崩潰,當然也可以導致進程崩潰。

一般而言,沒有絕對必要的共享內存空間的需求就不要使用線程,用進程會安全很多。


嚴格的說沒有「線程崩潰」,只是觸發了SIGSEGV (Segmentation Violation/Fault)。如果沒有設置對應的Signal Handler操作系統就自動終止進程(或者說默認的Signal Handler就是終止進程);如果設置了,理論上可以恢復進程狀態繼續跑(用longjmp之類的工具)


線程有自己的 stack,但是沒有單獨的 heap,也沒有單獨的 address space。

只有進程有自己的 address space,而這個 space 中經過合法申請的部分叫做 process space。Process space 之外的地址都是非法地址。

當一個線程向非法地址讀取或者寫入,無法確認這個操作是否會影響同一進程中的其它線程,所以只能是整個進程一起崩潰。


1.進程(主線程)創建了多個線程,多個子線程均擁有自己獨立的棧空間(存儲函數參數、局部變數等),但是多個子線程和主線程共享堆、全局變數等非棧內存。

2.如果子線程的崩潰是由於自己的一畝三分地引起的,那就不會對主線程和其他子線程產生影響,但是如果子線程的崩潰是因為對共享區域造成了破壞,那麼大家就一起崩潰了。

3.舉個栗子:主線程是一節車廂的乘務員,諸多乘客(也就是子線程)就是經過乘務員(主線程)檢票確定可以進入車廂的,也就是主線程創建了諸多子線程,每個子線程有自己獨立的區域(座位啊啥的),但是諸多乘客和乘務員共享走廊啊衛生間啊等等,如果其中一名乘客座位壞了,摔了(可以認為奔潰了),那麼其他乘客和乘務員都不受影響,但是如果乘客將衛生間給破壞了,他也無法使用衛生間(崩潰了),其他乘客和乘務員也不能用衛生間,好吧,那麼大家一起憋著吧(崩潰了)。


  • 進程是系統進行資源分配的基本單位,有獨立的內存地址空間; 線程是CPU調度的基本單位,沒有單獨地址空間,有獨立的棧,局部變數,寄存器,程序計數器等
  • 線程雖然有自己的堆棧和局部變數,但線程沒有單獨的地址空間,一個線程死掉就等於整個進程死掉

崩潰不崩潰要是是不是把數據寫臟。一般崩潰肯定伴隨棧溢出、讀取或者訪問了非法地址。


以下回答有不準確的地方,待有空回來填坑
2017.1.2

現代操作系統對於線程的支持方式不同,導致題主的問題在不同的操作系統下有不同的結果。

所謂現代的操作系統,是指支持多用戶,支持並行處理的操作系統。鑒於此因,操作系統一般都設計成支持兩種工作模式,user mode和kernel mode,這兩種模式相互隔絕無法直接訪問,避免用戶程序對於底層資源的直接訪問,通過system call的調用實現交互目的,從而實現操作系統對資源分配的公平和系統的高效率。

對於linux而言,很多應用如java,oracle,其對線程的支持是在user mode內實現的,而linux的scheduler(任務調度器)卻是工作在kernel mode的,對於linux的job scheduler而言,他的調度對象還是進程,線程這個概念對他而言是透明的。就像一個大公司的老闆,他的管理單元是部門,不會細究部門內某個人的事情。所以,對於題主的問題在linux下,線程異常退出的結果就是其父進程也跟著退出,即使這個線程的父進程下的其他多個兄弟線程都工作正常。我們在平常的工作中應該經常遇到過由於某個java線程異常退出而導致整個tomcat進程重啟或退出,就是由於這個原因。

而信奉扁平式管理的fans MS windows(win 2000?以後)以後及SUN的solaris 8(?)以後版本,他們的scheduler是可以直接對線程操作的,他們不僅像linux一樣,為每一個進程維護相應的PCB(process control block),針對線程還維護了一套相應的Thread Control Block - TCB, 以實現context switch。 solaris甚至突破了一個進程調用多個線程的思路,衍生了多個進程對應更多個線程執行同一個任務的實現方式。


線程崩潰一般是資源同步失敗或者乾脆就沒同步造成的內存訪問/讀寫錯誤。更高級一點的就是邏輯上的錯誤了。


exit() _exit _EXIT() abort() 都會造成進程退出
我不知道你說的崩潰屬於哪一種?


根據我實際在win下寫java 和c#代碼的情況,c#線程崩潰會導致進程也crash,所以c#線程必須要套個try catch。java則不會。所以我覺得可能是與編程語言不同的處理有關


線程崩潰,是否影響進程,要看情況吧。
如果只有這一個線程,進程肯定要跟著崩潰了

如果有多個線程,其它的線程應該不受影響吧。不然多線程有什麼意義


推薦閱讀:

TAG:軟體 | 計算機 | 多線程 | 線程 |