做逆戰(zhàn)網(wǎng)站的名字嗎網(wǎng)站收錄查詢網(wǎng)
文章目錄
- Windows和Linux平臺的線程
- 線程
- 構(gòu)造函數(shù)
- 模板參數(shù)包
最近發(fā)現(xiàn)C++11的線程庫還沒有進行總結(jié),因此本篇對于C++11當中新增的線程庫的一些基本用法進行總結(jié)
Windows和Linux平臺的線程
在Linux平臺下是存在一些原生的線程系統(tǒng)調(diào)用的,比如有pthread_create這樣的系統(tǒng)調(diào)用,而在C++11標準之后,C++自己的標準庫中也出現(xiàn)了有關(guān)線程的調(diào)用庫,這樣最大的好處就是只要使用的是C++提供的線程庫,這樣不管是在Linux下還是在Windows下都是可以使用的,提供了一個跨平臺的好處,因為這本身是屬于語言本身的
對于線程庫當中的實現(xiàn),其實就是把這樣的類unix平臺的接口和Windows的原生接口進行了一個條件編譯,當檢測到時WIN32的系統(tǒng)的時候,就使用的是Windows提供的原生的線程,而如果識別到時unix的系統(tǒng),就使用unix提供的線程,具體可以理解為下面這樣
#ifdef _WIN32
CreateThread()
#else
pthread_create()
#endif
線程
C++語言本身提供的這個線程,是一個用類進行封裝的線程:
也提供了一些成員函數(shù)
構(gòu)造函數(shù)
對于一個類來說,首先要看一下它的構(gòu)造函數(shù),看一下可以用什么樣的方法來構(gòu)造出這個函數(shù)
在上面的這四種構(gòu)造函數(shù)中出現(xiàn)了一些熟悉的身影,默認構(gòu)造函數(shù)是一個無參的構(gòu)造函數(shù),表示的是一個空線程,不啟動,其次是一個模板,在這個模板中帶有的是一個可變參數(shù)包,并且還有萬能引用等,這些后續(xù)進行代碼實踐,需要注意的是其中的Fn表示的是一個可執(zhí)行對象,可以是函數(shù)指針,仿函數(shù),lambda表達式,包裝器等等
從下面的拷貝函數(shù)可以看出,線程不支持拷貝構(gòu)造,但是支持移動構(gòu)造
模板參數(shù)包
為什么要誕生出這個模板參數(shù)包來進行構(gòu)造函數(shù)?先看看Linux下的線程創(chuàng)建是怎么創(chuàng)建的
如圖所示的是Linux下的線程創(chuàng)建的系統(tǒng)調(diào)用,第一個參數(shù)是線程的tid,這里就不多介紹了,重點是后面的函數(shù)指針,后面的arg表示的是函數(shù)指針的參數(shù),那這就意味著會用到強轉(zhuǎn)這樣的信息來進行參數(shù)的解析,如果使用原生的方式要傳遞多個參數(shù),通常要把這些信息放到一個結(jié)構(gòu)體當中:
#include <iostream>
#include <unistd.h>
#include <string>
using namespace std;struct thread_data
{thread_data(const string &message, int id) : _message(message), _id(id) {}string _message;int _id;
};void *routine(void *arg)
{struct thread_data *td = (struct thread_data *)arg;cout << td->_message << " : " << td->_id << endl;return nullptr;
}int main()
{pthread_t tid;for (int i = 0; i < 5; i++){thread_data td("這是線程", i);pthread_create(&tid, nullptr, &routine, (void *)&td);pthread_join(tid, nullptr);}return 0;
}
而在C++11的庫當中,如果使用這個模板參數(shù)包,就可以很方便的直接進行使用了:
#include <iostream>
#include <thread>
#include <windows.h>
#include <functional>
using namespace std;void func1(const string& message, int id)
{cout << message << " " << id << endl;
}struct func3
{void operator()(const string& message, int id){cout << message << " " << id << endl;}
};int main()
{// 使用函數(shù)指針string tmp1 = "這是函數(shù)指針的方法";int id1 = 1;thread t1(&func1, tmp1, id1);Sleep(1000);// 使用lambda表達式string tmp2 = "這是lambda的方法";int id2 = 2;thread t2([&](const string& message, int id) {cout << message << " " << id << endl;}, tmp2, id2);Sleep(1000);// 使用仿函數(shù)string tmp3 = "這是仿函數(shù)的方法";int id3 = 3;func3 f3;thread t3(f3, tmp3, id3);Sleep(1000);// 使用包裝器function<void(const string&, int)> func4 = func1;string tmp4 = "這是包裝器的方法";int id4 = 4;thread t4(func4, tmp4, id4);Sleep(1000);// 回收等待t1.join();t2.join();t3.join();t4.join();return 0;
}
如上所示是四種可執(zhí)行方式調(diào)用線程的方式