2011-01-21 38 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); 
} 
相关问题