C++11——多執行緒程式設計3
阿新 • • 發佈:2021-11-08
樓主應該翻譯: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; }