首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >正在从另一个线程取消boost线程

正在从另一个线程取消boost线程
EN

Stack Overflow用户
提问于 2015-06-02 04:44:18
回答 2查看 505关注 0票数 0

有没有办法从另一个线程中取消boost::thread,如下所示?:

代码语言:javascript
复制
boost::thread* thread1(0);
boost::thread* thread2(0);

thread2 = new boost::thread([&](){
   //some expensive computation that can't be modified
  if(thread1)
    thread1->interrupt();  
});

thread1 = new boost::thread([&]() {
  //some other expensive computation that can't be modified
  if(thread2)
    thread2->interrupt();  
});

thread1->join();
thread2->join();

delete thread1;
delete thread2;

现在,这两个昂贵的计算都会在不被中断的情况下完成。我认为连接将被视为中断点,并且主线程将在两个代价高昂的计算中的一个完成后继续。

EN

回答 2

Stack Overflow用户

发布于 2015-06-02 04:56:21

一般来说,如果没有被终止的线程的协作,一个线程没有可移植的方法来终止另一个线程。这个问题似乎偶尔会出现(参见herehere -尽管你的问题并不完全相同)。

如果您希望主线程在第一个线程终止后继续运行,则可以创建一个condition,每个子线程在结束时都会触发。

此时,您可以让另一个线程继续运行(可能是detach),也可以直接终止所有线程。

票数 5
EN

Stack Overflow用户

发布于 2016-02-12 06:58:09

对于兼容POSIX的系统(例如,Linux),不可移植的解决方案是先使用pthread_cancel(),然后在Boost线程的native_handle()成员上使用pthread_join(),该成员的类型为pthread_t (同样,仅在兼容POSIX的系统上使用)。我不能为其他系统说话,比如Windows)。

此外,您必须使用boost::scoped_thread而不仅仅是boost::thread,这样您就可以“覆盖”(不是OO意义上的) Boost将在线程被销毁时执行的联接/分离行为。这是必要的,因为当您在boost::thread上调用pthread_cancelpthread_join时,boost::thread对象仍然是“可接合的”(即boost::thread::joinable()返回true),因此析构函数将根据documentation表现出未定义的行为。

话虽如此,如果在您的应用程序中需要像这样的与平台相关的取消线程的解决方案,我不确定使用boost::threads而不是普通的pthreads能获得多少好处;不过,我认为可能有这样的用例。

下面是一个代码示例:

代码语言:javascript
复制
// compilation: g++ -pthread -I/path/to/boost/include -L/path/to/boost/libs -lboost_thread main.cpp

#include <cstdio>
#include <pthread.h>
#include <boost/thread/scoped_thread.hpp>

typedef struct pthreadCancelAndJoin
{
    void operator()(boost::thread& t)
    {
        pthread_t pthreadId = t.native_handle();
        int status = pthread_cancel(pthreadId);
        printf("Cancelled thread %lu: got return value %d\n", pthreadId, status);

        void* threadExitStatus;
        status = pthread_join(pthreadId, &threadExitStatus);
        printf("Joined thread %lu: got return value %d, thread exit status %ld\n",
               pthreadId, status, (long)threadExitStatus);
    }
} pthreadCancelAndJoin;

void foo()
{
    printf("entering foo\n");
    for(int i = 0; i < 2147483647; i++) printf("f");  // here's your 'expensive computation'
    for(int i = 0; i < 2147483647; i++) printf("a");
    printf("foo: done working\n");  // this won't execute
}

int main(int argc, char **argv)
{
    boost::scoped_thread<pthreadCancelAndJoin> t1(foo);
    pthread_t t1_pthread = t1.native_handle();

    sleep(1);  // give the thread time to get into its 'expensive computation';
               //   otherwise it'll likely be cancelled right away

    // now, once main returns and t1's destructor is called, the pthreadCancelAndJoin
    //   functor object will be called, and so the underlying p_thread will be cancelled
    //   and joined

    return 0;
}

当线程到达“取消点”时,pthread_cancel()将取消线程(假设cancel type and cancel state是它们的默认值,boost::thread对象就是这种情况);有关所有取消点的列表,请参阅pthreads man page。您会注意到,这些取消点包括许多更常见的系统调用,如writereadsleepsendrecvwait等。

如果您的“昂贵的计算”包括在最低级别(例如,在代码示例中,printf最终调用write)调用这些调用的任何,那么它将被取消。

最棒的是,Valgrind报告此解决方案没有内存泄漏或内存错误。

最后,请注意您在问题中的误解:

我认为joins将被视为中断点...

就这一点而言,join或任何boost::thread中断函数仅被视为调用 it的线程的中断点。由于您的主线程正在调用join(),因此主线程是遇到中断点的线程,而不是它试图加入的线程。例如,如果你在某个线程中调用thread1.interrupt(),然后thread1调用thread2.join(),那么thread1就是那个被中断的线程。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30582946

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档