2011-01-21 40 views
22

我在Linux(CentOS 5.3)產生多個線程的C++程序,這些線程在無限循環中執行作業並在特定的分鐘內休眠。 現在我不得不取消正在運行的線程,以防萬一有新的配置通知進來並且新啓動一組新的線程,爲此我已經使用了pthread_cancel。 我觀察到的結果是,即使接收到取消指示,線程也沒有停止,甚至有一些睡眠線程在睡眠完成後出現。使用pthread_cancel取消線程:很好的做法或不好

由於行爲不是所期望的,所以在所提到的場景中使用pthread_cancel會引發關於做法好壞的問題。

請評論上述場景中的pthread_cancel用法。

回答

39

一般來說,線程取消並不是一個好主意。只要有可能,最好是有一個共享標誌,線程使用它來擺脫循環。這樣,您將讓線程在實際退出之前執行任何可能需要執行的清理。

關於線程未實際取消的問題,POSIX規範確定了一組取消點(man 7 pthreads)。線程只能在這些點上取消。如果您的無限循環不包含取消點,則可以通過呼叫pthread_testcancel來添加取消點。如果pthread_cancel已被調用,則此時將採取行動。

+5

+1爲避免取消,這是最快的方式,內存泄漏,更糟。問禮貌地:) :) – 2011-01-21 18:56:02

+1

好像我必須改變使用共享標誌終止線程的邏輯。 但是在其他說明我的程序有線程取消狀態設置爲異步,我相信,這是相關的立即終止線程後調用各自的清理處理程序。 – Mandar 2011-01-23 14:09:23

0

我會使用boost :: asio。

喜歡的東西:

struct Wait { 
    Wait() : timer_(io_service_), run_(true) {} 

    boost::asio::io_service io_service_; 
    mutable boost::asio::deadline_timer timer_; 
    bool run_; 
}; 

void Wait::doWwork() { 
    while (run) { 
    boost::system::error_code ec; 
    timer_.wait(ec); 
    io_service_.run(); 
    if (ec) { 
     if (ec == boost::asio::error::operation_aborted) { 
     // cleanup 
     } else { 
     // Something else, possibly nasty, happened 
     } 
    } 
    } 
} 

void Wait::halt() { 
    run_ = false; 
    timer_.cancel(); 
} 

一旦你得到了你的頭圓它,ASIO是一個奇妙的工具。

0

你可以做下面的代碼的等價物。

#include <pthread.h> 
#include <cxxabi.h> 
#include <unistd.h> 
... 
void *Control(void* pparam) 
{ 
    try 
    { 
     // do your work here, maybe long loop 
    } 
    catch (abi::__forced_unwind&) 
    { // handle pthread_cancel stack unwinding exception 
     throw; 
    } 
    catch (exception &ex) 
    { 
     throw ex; 
    } 
} 

int main() 
{ 
    pthread_t tid; 
    int rtn; 
    rtn = pthread_create(&tid, NULL, Control, NULL); 

    usleep(500); 
    // some other work here 

    rtn = pthtead_cancel(tid); 
} 
相關問題