2010-09-29 202 views
17

我使用pthread_create創建多個子線程。一次,主線程想要殺死所有的子線程或者會有分段失敗。我應該使用哪個函數來完成該功能?我搜索了谷歌的答案,並得到了像pthread_kill這樣的功能。但我不知道應該發送給子線程來殺死它們的信號。我的運行環境是RHEL 5.4,編程語言是C.對於pthread,如何從主線程中殺死子線程

+2

哇,殺死所有線程,因爲會有段錯誤?你在開玩笑嗎?我從來沒有像這樣處理過一些代碼。 – 2010-09-29 14:58:33

+1

真正地說,我gdb是主線程退出全局對象時發現的核心轉儲被解構的。所以一些子線程當前可能使用這樣的變量,並且段錯誤被打印在我的屏幕上。雖然,邏輯是正確的,並且段錯誤對我的程序沒有任何影響,因爲它已完成。 – terry 2010-10-01 08:50:07

+2

修復邏輯。如果其他線程仍在做有用的工作,爲什麼你試圖終止程序?如果其他線程仍然需要這些對象,即使'main'超出了範圍,爲什麼它們被分配在'main's棧? – 2011-08-30 13:08:34

回答

20

可以使用pthread_cancel「取消」線程。然而,這通常不是最佳實踐,儘管在SEGFAULT等極端情況下,它可能是一種合理的方法。

+1

這個URL有一個例子http://linux.die.net/man/3/pthread_cleanup_push – enthusiasticgeek 2013-03-19 16:47:00

+4

爲什麼'pthread_cancel'不被認爲是最佳實踐?如果這不是最佳實踐,那是什麼? – darnir 2016-08-06 21:55:42

6

你應該送SIG_TERM您的每一個線程,使用

int pthread_kill(pthread_t thread, int sig); 

一個快速的方法來擺脫所有線程的(除了主)是fork()和保持與孩子去。
不超乾淨。

if (fork()) exit(0); // deals also with -1... 
24

一般情況下,你真的不想要暴力殺死一個子線程,而是你要問它終止。這樣你就可以確定孩子在安全的地方戒菸,所有的資源都被清理乾淨。

我通常會用父母與子女之間的一小段共享狀態來做到這一點,以允許父母向每個孩子傳達「退出請求」。這可以是每個孩子的布爾值,由互斥體保護。孩子定期檢查這個值(每個循環迭代,或者你的子線程中的任何方便的檢查點)。在看到「quit_request」爲真時,子線程清理並調用pthread_exit

在家長方面,「kill_child」例行看起來是這樣的:

acquire shared mutex 
set quit_request to true 
pthread_join the child 

將在pthread_join可能需要一些時間,這取決於孩子檢查的頻率其辭職請求。確保你的設計可以處理任何延遲。

+0

儘管在修改線程之間共享的任何內存之前獲取互斥體通常是一種很好的做法,但這是一個檢查非零(或錯誤)狀態的單個標誌,這意味着您並不需要搶一個互斥體。 在這種情況下,從數據一致性的角度來看,確實沒有太多可能出錯的地方。 – 2013-07-26 19:51:05

+2

@Brent:[This question](http://stackoverflow.com/questions/21183261/is-a-race-condition-possible-when-only-one-thread-writes-to-a-bool-variable-in -c)顯示了一個例子,即一次寫入的單個標誌可以在編譯器優化之後導致競爭條件。 – dshepherd 2015-05-30 15:27:16

+0

美麗,這件作品奇妙。 – djthoms 2016-06-24 22:19:57

2

您可以爲整個程序使用全局變量。

int _fCloseThreads;

當您希望線程退出執行時,將其設置爲1。讓線程在它們的「循環」中檢查變量,並在設置爲1時很好地退出。無需使用互斥鎖保護它。

您需要等待線程退出。你可以使用連接。另一種方法是當一個線程進入它的線程進程時增加一個計數器,然後在計數器退出時取消計數器。櫃檯需要是一個全球性的。在計數器上使用gcc原子操作。主線程在設置fCloseThreads之後,可以通過循環,休眠和檢查計數等待計數器變爲零。

最後,您可能會檢出pthread_cleanup_push和pop。它們是允許線程在其代碼中的任何地方取消的模型(使用longjump),然後在退出threadproc之前調用最終的清除函數。你基本上把cleanup_push放在你的threadproc和cleanup_pop的底部,創建一個展開函數,然後在某些取消點上,一個被pthread_cancel()調用取消的線程將跳回threadproc並調用展開函數。

+1

http://linux.die.net/man/3/pthread_cleanup_push有一個例子。 – enthusiasticgeek 2013-03-19 16:49:30