自毁 std::thread

huangapple go评论55阅读模式
英文:

self destructive std:thread

问题

我将有一个能生成自毁线程的函数。问题是在创建的线程结束之前,我不能重用该函数。另一方面,我希望新创建的线程能在函数作用域外继续运行,并在线程完成时被销毁。

我的代码如下。

#include <iostream>
#include <thread>
#include <chrono>

struct ThreadGaurd
{
public:
    ThreadGaurd(void (*Func) (int) , int number);
    ~ThreadGaurd();
private:
public:
    std::thread m_Thread;
private:
};

void CreateThread()
{
    static int Counter = 0;
    ThreadGaurd m_Thread([](int counter)
    {
        std::chrono::duration<double, std::milli> m_Duration(500);

        while (true) {
            std::this_thread::sleep_for(m_Duration);

            std::cout << "My " << counter << "'th Thread is Running";
        }
    }, Counter);

    return;
} 

int main(int argc, char *argv[])
{
    CreateThread();
    CreateThread();
    return 0;
}

ThreadGaurd::ThreadGaurd(void (*Func)(int), int number) : m_Thread(Func,number)
{
}

ThreadGaurd::~ThreadGaurd()
{
    if (m_Thread.joinable())
        m_Thread.join(); 
}
英文:

I'm going to have a function capable of generating auto-destructive threads. The problem is that I'm not allowed to reuse the function until the created thread has finished. On the other hand, I want the spawned thread to continue running outside the scope of the function and be destroyed whenever the thread is done.

My code is as follows.

#include &lt;iostream&gt;
#include &lt;thread&gt;
#include &lt;chrono&gt;

struct ThreadGaurd
{
public:

    ThreadGaurd(void (*Func) (int) , int number);

    ~ThreadGaurd();
private:
public:

    std::thread m_Thread;
private:
};


void CreateThread()
{
    static int Counter = 0;
    ThreadGaurd m_Thread([](int counter)
    {
        std::chrono::duration&lt;double, std::milli&gt; m_Duration(500);

        while (true) {
            std::this_thread::sleep_for(m_Duration);

            std::cout &lt;&lt; &quot;My &quot; &lt;&lt; counter &lt;&lt; &quot;&#39;th Thread is Running&quot;;
        }
    }, Counter);

    return;
} 

int main(int argc, char *argv[])
{
    CreateThread();
    CreateThread();
    return 0;
}

ThreadGaurd::ThreadGaurd(void (*Func)(int), int number) : m_Thread(Func,number)
{
}

ThreadGaurd::~ThreadGaurd()
{
    if (m_Thread.joinable())
        m_Thread.join(); 
}

答案1

得分: 4

你想要在线程上调用 std::thread::detach。在 detach 返回之后,可以安全地销毁 std::thread 对象,因为线程不再与该对象关联,将继续独立运行。

以下代码演示了使用 detach

#include <iostream>
#include <thread>
#include <chrono>

using std::cout, std::endl;
using namespace std::chrono_literals;

template<class F>
void create_detached_thread(F&& func) {
    std::thread th{std::forward<F>(func)};
    th.detach();
}

int main(int argc, const char *argv[]) {
    cout << "Main started" << endl;

    create_detached_thread([]() {
        cout << "First thread starting" << endl;
        std::this_thread::sleep_for(400ms);
        cout << "First thread done" << endl;
    });

    create_detached_thread([]() {
        cout << "Second thread starting" << endl;
        std::this_thread::sleep_for(200ms);
        cout << "Second thread done" << endl;
    });

    cout << "Main sleeping" << endl;
    std::this_thread::sleep_for(1s);
    cout << "Main done" << endl;
    return 0;
}

输出:

Main started
Main sleeping
Second thread starting
First thread starting
Second thread done
First thread done
Main done

如在这个 答案 中所解释的,必须在销毁 std::thread 对象之前调用 joindetach,否则将调用 std::terminate

如果需要使用 detach,可能需要提供同步机制,以确保主线程在所有已分离的线程完成之前不会结束。

英文:

You want to call std::thread::detach on the thread. After detach returns, it is safe to destroy the std::thread object as the thread is no longer associated with the object and will continue running independently.

The following code demonstrates using detach.

Sample Code

#include &lt;iostream&gt;
#include &lt;thread&gt;
#include &lt;chrono&gt;

using std::cout, std::endl;
using namespace std::chrono_literals;

template&lt;class F&gt;
void create_detached_thread(F&amp;&amp; func) {
    std::thread th{std::forward&lt;F&gt;(func)};
    th.detach();
}

int main(int argc, const char *argv[]) {
    cout &lt;&lt; &quot;Main started&quot; &lt;&lt; endl;

    create_detached_thread([]() {
        cout &lt;&lt; &quot;First thread starting&quot; &lt;&lt; endl;
        std::this_thread::sleep_for(400ms);
        cout &lt;&lt; &quot;First thread done&quot; &lt;&lt; endl;

    });

    create_detached_thread([]() {
        cout &lt;&lt; &quot;Second thread starting&quot; &lt;&lt; endl;
        std::this_thread::sleep_for(200ms);
        cout &lt;&lt; &quot;Second thread done&quot; &lt;&lt; endl;
    });

    cout &lt;&lt; &quot;Main sleeping&quot; &lt;&lt; endl;
    std::this_thread::sleep_for(1s);
    cout &lt;&lt; &quot;Main done&quot; &lt;&lt; endl;
    return 0;
}

Output

Main started
Main sleeping
Second thread starting
First thread starting
Second thread done
First thread done
Main done

As explained in this answer, you have to call either join or detach on a thread before the std::thread object is destroyed, otherwise std::terminate is called.

If you need to use detach, you will probably want to provide a synchronization mechanism so that the main thread will not end unless all of the detach'ed threads have finished.

Update

The following code is the same as above except it uses a std::atomic&lt;int&gt; to wait for the two detached threads to finish before allowing main to finish.

#include &lt;atomic&gt;
#include &lt;iostream&gt;
#include &lt;thread&gt;
#include &lt;chrono&gt;

using std::cout, std::endl;
using namespace std::chrono_literals;

template&lt;class F&gt;
void create_detached_thread(F&amp;&amp; func) {
    std::thread th{std::forward&lt;F&gt;(func)};
    th.detach();
}

int main(int argc, const char *argv[]) {
    cout &lt;&lt; &quot;Main started&quot; &lt;&lt; endl;

    std::atomic&lt;int&gt; ndone{};

    create_detached_thread([&amp;]() {
        cout &lt;&lt; &quot;First thread starting&quot; &lt;&lt; endl;
        std::this_thread::sleep_for(400ms);
        cout &lt;&lt; &quot;First thread done&quot; &lt;&lt; endl;
        ++ndone;
        ndone.notify_one();
    });

    create_detached_thread([&amp;]() {
        cout &lt;&lt; &quot;Second thread starting&quot; &lt;&lt; endl;
        std::this_thread::sleep_for(200ms);
        cout &lt;&lt; &quot;Second thread done&quot; &lt;&lt; endl;
        ++ndone;
        ndone.notify_one();
    });

    cout &lt;&lt; &quot;Main sleeping&quot; &lt;&lt; endl;
    ndone.wait(0);
    ndone.wait(1);
    cout &lt;&lt; &quot;Main done&quot; &lt;&lt; endl;
    return 0;
}

huangapple
  • 本文由 发表于 2023年5月26日 09:44:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/76337172.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定