文章目錄
- 描述
- 函數成員簡介
- 總結
描述
- 頭檔案
<thread>
- 聲明方式:
std::thread <obj>
-
簡介
線程在構造關聯的線程對象時立即開始執行,從提供給作為構造函數參數的頂層函數開始。如果頂層函數抛出異常,則調用
。正如我們之前幾篇說過的thread可以通過std::terminate
和std::async
類對修改共享變量,并将傳回值傳遞給調用方。如果共享變量在該過程中需要進行同步,則就需要我們說過的std::promise
和std::mutex
std::condition_variable
。
不支援拷貝構造和指派,如果需要将目前t1 對象指派給t2對象,需要通過移動指派std::thread
,即将t1的位址以及内容全部指派給t2對象才行。std::move
函數成員簡介
-
構造函數(建立線程的多種方式)
a. 類對象的拷貝建立線程
b. 類對象的引用建立線程
c. 移動複制
std::move
對象建立線程
d. 臨時建立的對象建立線程
e. 函數名建立線程
f. lamda函數建立線程
g. 類對象的拷貝的成員函數 建立線程
h. 類對象的位址的成員函數 建立線程
#include <iostream>
#include <utility>
#include <thread>
#include <chrono>
void f1(int n)
{
for (int i = 0; i < 5; ++i) {
std::cout << "Thread 1 executing\n";
++n;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
void f2(int& n)
{
for (int i = 0; i < 5; ++i) {
std::cout << "Thread 2 executing\n";
++n;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
class foo
{
public:
void bar()
{
for (int i = 0; i < 5; ++i) {
std::cout << "Thread 3 executing\n";
++n;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
int n = 0;
};
class baz
{
public:
void operator()(int n)
{
for (int i = 0; i < 5; ++i) {
std::cout << "Thread 4 executing\n";
++n;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
int n = 0;
};
int main()
{
int n = 0;
foo f;
baz b;
std::thread t1; // t1 is not a thread
std::thread t2(f1, n + 1); // 普通函數名建立線程,傳遞函數參數為值
std::thread t3(f2, std::ref(n)); // 普通函數名建立線程,傳遞函數參數為引用
std::thread t4(std::move(t3)); // 類對象的移動指派,使用std::move
std::thread t5(&foo::bar, &f); // 類對象的拷貝的位址的成員函數
std::thread t6(b,6); // 類對象建立線程,預設執行operator ()函數
std::thread t7([](int x){return x*x;},6);//lamda函數建立子線程
std::thread t8(std::ref(b),6);//類對象的引用建立
std::thread t9(baz(),6);//臨時對象建立
t2.join();
t4.join();
t5.join();
t6.join();
t7.join();
t8.join();
t9.join();
std::cout << "Final value of n is " << n << '\n';
std::cout << "Final value of foo::n is " << f.n << '\n';
}
- 輸出如下,由于輸出為線程間交叉執行,輸出會有點亂:
Thread 2 executing
Thread 4 executing
Thread 1 executing
Thread 3 executing
Thread 4 executing
Thread 4 executing
Thread 2 executing
Thread 1 executing
Thread 3 executing
Thread 4 executing
Thread 4 executing
Thread 4 executing
Thread 2 executing
Thread 1 executing
Thread 4 executing
Thread 3 executing
Thread 4 executing
Thread 4 executing
Thread 2 executing
Thread 4 executing
Thread 4 executing
Thread 1 executing
Thread 3 executing
Thread 4 executing
Thread 2 executing
Thread 4 executing
Thread 4 executing
Thread 3 executing
Thread 4 executing
Thread 1 executing
Final value of n is 5
Final value of foo::n is 5
-
std::thread::joinable
檢查 thread 對象是否辨別活躍的執行線程,是傳回true,否則傳回false
如下代碼
#include <iostream>
#include <thread>
#include <chrono>
void foo()
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
int main()
{
//剛建立好的線程對象是不活躍的
std::thread t;
std::cout << "before starting, joinable: " << std::boolalpha << t.joinable()
<< '\n';
//建立線程并執行代碼,但未合并,則它是活躍的
t = std::thread(foo);
std::cout << "after starting, joinable: " << t.joinable()
<< '\n';
//線程合并之後變為不活躍的
t.join();
std::cout << "after joining, joinable: " << t.joinable()
<< '\n';
}
- 輸出如下:
before starting, joinable: false
after starting, joinable: true
after joining, joinable: false
-
std::thread::join
阻塞線程成員,直到線程函數代碼執行完畢傳回
代碼如下:
#include <iostream>
#include <thread>
#include <chrono>
void foo()
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
void bar()
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
int main()
{
std::cout << "starting first helper...\n";
std::thread helper1(foo);
std::cout << "starting second helper...\n";
std::thread helper2(bar);
std::cout << "waiting for helpers to finish..." << std::endl;
helper1.join();
helper2.join();
std::cout << "done!\n";
}
- 輸出如下:
starting first helper...
starting second helper...
waiting for helpers to finish...
done!
-
std::thread::detach
從 thread 對象分離執行的線程,允許執行獨立地執行線程
一旦線程退出,則釋放所有配置設定的資源。
如下代碼:
#include <iostream>
#include <chrono>
#include <thread>
void independentThread()
{
std::cout << "Starting concurrent thread.\n";
std::this_thread::sleep_for(std::chrono::seconds(2));
std::cout << "Exiting concurrent thread.\n";
}
void threadCaller()
{
std::cout << "Starting thread caller.\n";
std::thread t(independentThread);
//這裡調用detach,則線程t将獨立執行,是以目前線程的輸出會早于t線程的輸出
t.detach();
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "Exiting thread caller.\n";
}
int main()
{
threadCaller();
std::this_thread::sleep_for(std::chrono::seconds(5));
}
- 輸出如下:
Starting thread caller.
Starting concurrent thread.
Exiting thread caller.
Exiting concurrent thread.
-
std::thread::swap
交換兩個線程的對象的檔案句柄
代碼如下:
#include <iostream>
#include <thread>
#include <chrono>
void foo()
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
void bar()
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
int main()
{
std::thread t1(foo);
std::thread t2(bar);
std::cout << "thread 1 id: " << t1.get_id() << std::endl;
std::cout << "thread 2 id: " << t2.get_id() << std::endl;
使用boost的swap和thread類封裝的swap函數效果類似,都會交換線程的檔案句柄
std::swap(t1, t2);
std::cout << "after std::swap(t1, t2):" << std::endl;
std::cout << "thread 1 id: " << t1.get_id() << std::endl;
std::cout << "thread 2 id: " << t2.get_id() << std::endl;
t1.swap(t2);
std::cout << "after t1.swap(t2):" << std::endl;
std::cout << "thread 1 id: " << t1.get_id() << std::endl;
std::cout << "thread 2 id: " << t2.get_id() << std::endl;
t1.join();
t2.join();
}
- 輸出如下:
thread 1 id: 0x70000f1e9000
thread 2 id: 0x70000f26c000
after std::swap(t1, t2):
thread 1 id: 0x70000f26c000
thread 2 id: 0x70000f1e9000
after t1.swap(t2):
thread 1 id: 0x70000f1e9000
thread 2 id: 0x70000f26c000