【问题标题】:How to join a std::thread from itself (in C++11)如何从自身加入 std::thread(在 C++11 中)
【发布时间】:2016-01-23 14:30:33
【问题描述】:

我有一个 std::thread 正在等待并从套接字读取。并且有一个指向此thread 的指针存储在某处。但是当发生不好的事情并且thread 结束时,我希望它调用一些导致加入该线程的函数,然后删除引用它的指针。 (我可以从线程内访问该指针)

我可以在另一个线程中执行此操作,但新线程成为问题。

【问题讨论】:

  • Join 必须发生在启动线程中。这意味着 那个 线程需要一个事件处理程序。你的启动线程有什么事件机制吗?
  • 如何通知启动线程该线程已结束?
  • @Farzam 不管你想要什么,没有“一个正确的方法”。最简单的方法可能是受互斥体保护的布尔值。
  • '当坏事发生时' - 比如什么?为什么线程必须“结束”?如果有异常,你可以用通常的方式捕捉它。
  • @MartinJames 当套接字关闭时线程可以结束。

标签: c++ multithreading c++11 boost-thread stdthread


【解决方案1】:

您可以在分离状态下创建线程,并使您的线程生命周期依赖于条件变量并在完成时切换布尔状态。

#include <thread>
#include <iostream>
#include <unistd.h>
#include <condition_variable>
#include <mutex>

class A {
    private:
        void Threadfunction();
        volatile bool class_running;
        volatile bool thread_running;
        std::condition_variable cv;
        std::mutex mu;
    public:
        A();
        ~A();
        void Stop();
};
A::A(){
    class_running = true;
    thread_running = false;
    std::thread t(&A::Threadfunction,this);
    t.detach();
}
A::~A(){
    if(class_running) {this->Stop();}
}
void A::Stop() {
    std::unique_lock<std::mutex> lk(mu);
    class_running = false;
    while(thread_running) {
        cv.wait(lk);
    }
    std::cout << "Stop ended " << std::endl;
}
void A::Threadfunction(){
    thread_running = true;
    std::cout << "thread started " << std::endl;
    while(class_running){
        // Do something
    }
    thread_running = false;
    cv.notify_one();
    std::cout << "thread stopped " << std::endl;
}
int main(){
    A a1;
    A a2;
    sleep(1);
    std::cout << "a1.Stop() called " << std::endl;
    a1.Stop();
    sleep(1);
    std::cout << "a2.Stop() not called but a2 goes out of scope and destructor is called " << std::endl;
}

【讨论】:

    【解决方案2】:

    改变你的设计,这样你就没有这个奇怪的要求了。一个简单的解决方案是将shared_ptrs 用于拥有线程并具有其他状态信息的控制结构。线程可以为这个控制结构持有一个shared_ptr,并使用它来向任何其他感兴趣的代码报告它的状态。当没有人再关心这个线程时,这个控制结构的最后一个shared_ptr 将消失并被销毁。

    【讨论】:

    • 投反对票,因为:“更改您的要求”与 OP 无关。并非总是可以更改要求。
    • @JonathanBen-Avraham 我非常不同意这样一种说法,即并非总是可以做到的答案不是相关的答案。
    • OP 需要一个解决方案。 @Conk 的帖子提供了一个解决方案。你的帖子没有。它只是暗示了一个解决方案,并没有说明需要说什么,即线程不能自行连接,但是当线程连接需要以本地的状态信息为条件时,有一些变通方法。线。如果您在帖子中说明您仅在上述评论中暗示的内容,即线程无法自行加入并解释原因,那将改善您的答案。
    • @JonathanBen-Avraham Conk 的回答是一种设计更改,它消除了要求,并不是一个特别好的要求。关键是要改变设计。没有更多细节,示例不太可能特别有用。我认为这对于非常复杂的代码来说是双重的,具有奇怪的同步黑客并且没有 cmets。
    • 一点也不奇怪。我最终来到这里是因为我有同样的情况。我有线程读取,线程发生异常,不需要退出清理。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-06
    • 2017-12-03
    • 2014-10-02
    • 1970-01-01
    • 1970-01-01
    • 2013-11-26
    相关资源
    最近更新 更多