簡體   English   中英

使用 std::thread & std::bind 在成員 function 中啟動線程

[英]Start thread within member function using std::thread & std::bind

我對下面的代碼快照幾乎沒有疑問。

1) 關於 pthread_create(),假設 Thread_1 創建 Thread_2。 據我了解,Thread_1 可以在不加入的情況下退出,但 Thread_2 仍將繼續運行。 在下面沒有 join() 的示例中,我無法運行線程並且我看到異常。

2)在幾個例子中,我看到沒有線程 object 的線程創建如下。 但是當我這樣做時,代碼被終止。

std::thread(&Task::executeThread, this);

I am compiling with below command.
g++ filename.cpp -std=c++11 -lpthread

但它仍然異常終止。 這是創建線程的正確方法還是有任何不同版本的 C++ (在我的項目中,他們已經在編譯但不確定版本)。

3)在我的項目代碼的幾個示例中,我看到了以下創建線程的方式。 但我無法使用下面的示例執行。

std::thread( std::bind(&Task::executeThread, this) );

下面是我的代碼快照。

#include <iostream>
#include <thread>

class Task
{
    public:
    void executeThread(void)
    {
        for(int i = 0; i < 5; i++)
        {
           std::cout << " :: " << i << std::endl;
        }
    }

    void startThread(void);
};

void Task::startThread(void)
{
    std::cout << "\nthis: " << this << std::endl;

#if 1
    std::thread th(&Task::executeThread, this);
    th.join(); // Without this join() or while(1) loop, thread will terminate
    //while(1);
#elif 0
    std::thread(&Task::executeThread, this);  // Thread creation without thread object
#else
    std::thread( std::bind(&Task::executeThread, this) );
    while(1);
#endif
}

int main()
{
    Task* taskPtr = new Task();
    std::cout << "\ntaskPtr: " << taskPtr << std::endl;

    taskPtr->startThread();

    delete taskPtr;
    return 0;
}

感謝和問候

毗濕奴比瑪

std::thread(&Task::executeThread, this); 語句創建和銷毀線程 object。 std::thread的析構函數在線程未加入或分離時調用std::terminate (就像在您的語句中一樣)。

沒有充分的理由在 C++11 中使用std::bind ,因為 lambda 在空間和速度方面更好。

在構建多線程代碼時,您需要在編譯和鏈接時指定-pthread選項。 Linker 選項-lpthread既不充分又不必要。

根據設計,您需要加入您生成的所有線程,或將它們分離。 請參閱例如關於加入/分離的 SO 問題

另請參閱cppreference,分離

如果 main() 在分離的線程仍在運行時退出,還要注意重要的警告

我也 100% 同意另一個答案中關於更喜歡綁定 lambda 的評論。

最后,不要陷入在 C++ 中的線程上執行 pthread_cancel 的誘惑。 參見例如pthread_cancel 被認為是有害的

  1. 在 C++ 中,對象具有生命周期。 這與處理 C 中的句柄有點不同。 在 C++ 中,如果您在一個 scope 中的堆棧上創建 object,則如果退出 Z31A1FD140BE4BEF2D8ZA11E,它將被銷毀。 這些規則有一些例外,例如std::move ,但根據經驗,您擁有 object 的生命周期。

  2. 這與上述相同的答案有關。 當你調用std::thread(&Task::executeThread, this); 您實際上是在調用線程構造函數。 這是線程生命周期和 object 生命周期的開始。 請注意,您在堆棧上創建了此 object。 如果您離開 scope {.. yourcode.. }將調用 DTor。 由於您在std::movejoindetatch之前完成了此操作,因此調用std::terminate()會引發異常。

  3. 你可以這樣創建一個線程。 如果您查看 std::thread::thread (構造函數)的鏈接文檔,則會以相同的方式創建 object foo 的示例。 你收到什么錯誤?

相關文檔:

一個。 std::thread::~thread()

灣。 std::thread::thread

c。C++ 的使用壽命

我個人建議了解 C++ 中對象的生命周期。 簡而言之,所有對象的生命周期都是在調用其構造函數時開始的。 當它們被殺死(如超出范圍)時,它們的析構函數被調用。 編譯器會為您處理此問題,因此如果您來自 C,它是一個新概念。

謝謝大家的意見。 作為線程創建的一部分,我錯過了線程 object。 因為這個雖然編譯,我得到了例外。 下面是我更新的代碼。 所有三種情況都運行良好。

#include <iostream>
#include <thread>

class Task
{
    public:
    void executeThread(std::string command)
    {
        for(int i = 0; i < 5; i++)
        {
            std::cout << command << " :: " << i << std::endl;
        }
    }

    void startThread(void);
    std::thread th2;
    std::thread th3;
};

void Task::startThread(void)
{
    std::cout << "\nthis: " << this << std::endl;

    #if 0
        std::thread th1(&Task::executeThread, this, "Thread1");
        th1.join(); // Without join(), thread will terminate
    #elif 0
        th2 = std::thread(&Task::executeThread, this, "Thread2");
        th2.join();
    #else
        th3 = std::thread( std::bind(&Task::executeThread, this, "Thread3") );
        th3.join();
    #endif
}

int main()
{
    Task* taskPtr = new Task();
    std::cout << "\ntaskPtr: " << taskPtr << std::endl;

    taskPtr->startThread();

    delete taskPtr;
    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM