c++11多线程编程(三):仔细地将参数传递给线程

来源:互联网 发布:linux mutex init 编辑:程序博客网 时间:2024/05/20 10:13

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

输出为:

In Main Thread : Before Thread Start x = 9 
Inside Thread x = 10 
In Main Thread : After Thread Joins x = 9 


即使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;}

输出:

In Main Thread : Before Thread Start x = 9 

Inside Thread x = 10 

In Main Thread : After Thread Joins x = 10 


指定一个类的成员函数的指针作为线程函数
将指针传递给成员函数作为回调函数,并将指针指向对象作为第二个参数

#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;}  





原创粉丝点击