1. 程式人生 > 其它 >C++11——多執行緒程式設計3

C++11——多執行緒程式設計3

樓主應該翻譯:https://thispointer.com/category/multithreading/

轉載來自:https://blog.csdn.net/lijinqi1987/article/details/78404092

要將引數傳遞給執行緒的可關聯物件或函式,只需將引數傳遞給std::thread建構函式。

預設情況下,所有的引數都將複製到新執行緒的內部儲存中。

#include <iostream>
#include <string>
#include <thread>
void threadCallback(int x, std::string str)
{
    std::cout 
<< "Passed Number = " << x << std::endl; std::cout << "Passed String = " << str << std::endl; } int main() { int x = 10; std::string str = "Sample String"; std::thread threadObj(threadCallback, x, str); threadObj.join(); return 0; }

不要將變數的地址從本地堆疊傳遞給執行緒的回撥函式。

因為執行緒 1 中的區域性變數可能已經銷燬,但執行緒 2 仍在嘗試通過其地址訪問它。
在這種情況下,訪問無效地址可能會導致意外行為

#include <iostream>
#include <thread>
void newThreadCallback(int* p)
{
    std::cout << "Inside Thread :  "" : p = " << p << std::endl;
    std::chrono::milliseconds dura(1000);
    std::this_thread::sleep_for(dura);
    
*p = 19; } void startNewThread() { int i = 10; std::cout << "Inside Main Thread : "" : i = " << i << std::endl; std::thread t(newThreadCallback, &i); t.detach(); std::cout << "Inside Main Thread : "" : i = " << i << std::endl; } int main() { startNewThread(); std::chrono::milliseconds dura(2000); std::this_thread::sleep_for(dura); return 0; }

同樣的,在傳遞指向堆記憶體的指標給heap時,因為某些執行緒可能在新執行緒嘗試訪問它之前刪除該記憶體。
在這種情況下,訪問無效地址可能會導致不可預測的行為。

#include <iostream>
#include <thread>
void newThreadCallback(int* p)
{
    std::cout << "Inside Thread :  "" : p = " << p << std::endl;
    std::chrono::milliseconds dura(1000);
    std::this_thread::sleep_for(dura);
    *p = 19;
    std::cout << *p << std::endl;
}
void startNewThread()
{
    int* p = new int();
    *p = 10;
    std::cout << "Inside Main Thread :  "" : *p = " << *p << std::endl;
    std::thread t(newThreadCallback, p);
    t.detach();
    delete p;
    p = NULL;
}
int main()
{
    startNewThread();
    std::chrono::milliseconds dura(2000);
    std::this_thread::sleep_for(dura);
    return 0;
}


給執行緒傳遞引用

由於引數被複制到新的執行緒堆疊,所以,如果想通過常用的方式傳遞引用,如:

#include <iostream>
#include <thread>

void threadCallback(int const& x) {
    int& y = const_cast<int&>(x);
    y++;
    std::cout << "Inside Thread x = " << x << std::endl;
}

int main() {
    int x = 9;
    std::cout << "In Main Thread : Before Thread Start x = " << x << std::endl;
    std::thread threadObj(threadCallback, x);
    threadObj.join();
    std::cout << "In Main Thread : After Thread Joins x = " << x << std::endl;
    return 0;
}

即使threadCallback接受引數作為引用,但是並沒有改變main中x的值,線上程引用外它是不可見的。
這是因為執行緒函式threadCallback中的x是引用複製在新執行緒的堆疊中的臨時值

如何修改:

使用 std::ref

#include <iostream>
#include <thread>

void threadCallback(int const& x) {
    int& y = const_cast<int&>(x);
    y++;
    std::cout << "Inside Thread x = " << x << std::endl;
}

int main() {
    int x = 9;
    std::cout << "In Main Thread : Before Thread Start x = " << x << std::endl;
    std::thread threadObj(threadCallback, std::ref(x));
    threadObj.join();
    std::cout << "In Main Thread : After Thread Joins x = " << x << std::endl;
    return 0;
}

指定一個類的成員函式的指標作為執行緒函式
將指標傳遞給成員函式作為回撥函式,並將指標指向物件作為第二個引數

#include <iostream>
#include <thread>
class DummyClass {
public:
    DummyClass()
    {}
    DummyClass(const DummyClass& obj)
    {}
    void sampleMemberFunction(int x)
    {
        std::cout << "Inside sampleMemberFunction " << x << std::endl;
    }
};
int main() {

    DummyClass dummyObj;
    int x = 10;
    std::thread threadObj(&DummyClass::sampleMemberFunction, &dummyObj, x);
    threadObj.join();
    return 0;
}