C++11——多线程编程3

翻译来自:https://thispointer.com//c11-multithreading-part-3-carefully-pass-arguments-to-threads/

要将参数传递给线程的可关联对象或函数,只需将参数传递给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;
}

 

posted @ 2021-11-08 18:09  冰糖葫芦很乖  阅读(59)  评论(0编辑  收藏  举报