簡體   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