繁体   English   中英

使用pthread_cancel取消线程:良好做法或不好

[英]Cancelling a thread using pthread_cancel : good practice or bad

我在Linux(CentOS 5.3)上有一个C ++程序,它产生多个线程,这些线程处于无限循环中以执行作业并在某些时间内休眠。 现在我必须取消正在运行的线程以防新的配置通知进入并重新启动新的线程集,我已经使用了pthread_cancel。 我观察到的是,即使在接收到取消指示后,线程也没有停止,甚至在睡眠完成后一些睡眠线程也会出现。

由于不需要这种行为,在上述场景中使用pthread_cancel会引发关于好坏练习的问题。

请评论上述场景中的pthread_cancel用法。

一般来说,线程取消并不是一个好主意。 只要有可能,最好有一个共享标志,线程使用该标志来突破循环。 这样,您将让线程执行在实际退出之前可能需要执行的任何清理。

在没有实际取消的线程问题上,POSIX规范确定了一组取消点( man 7 pthreads )。 线程只能在这些点取消。 如果您的无限循环不包含取消点,您可以通过调用pthread_testcancel添加一个取消点。 如果已调用pthread_cancel ,则此时将对其执行操作。

如果您正在编写异常安全的C ++代码(请参阅http://www.boost.org/community/exception_safety.html ),那么您的代码自然可以用于线程取消。 glibs在线程取消时引发C ++异常 ,因此你的析构函数可以进行适当的清理。

我会使用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就是一个很棒的工具。

您可以执行以下代码的等效操作。

#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 );
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM