C++11 多线程 基础
C++11開始支持多線程編程,之前多線程編程都需要系統的支持,在不同的系統下創建線程需要不同的API如pthread_create(),Createthread(),beginthread()等,使用起來都比較復雜,C++11提供了新頭文件<thread>、<mutex>、<atomic>、<future>等用于支持多線程。
使用C++11開啟一個線程是比較簡單的,下面來看一個簡單的例子:
#include <thread>
#include <iostream>
?
void hello()
{
??? std::cout << "Hello from thread " << std::endl;
}
?
int main()
{
??? std::thread t1(hello);
??? t1.join();
std::cout<<"Main Thread"<<std::endl;
??? return 0;
}
運行結果:
說明,通過thread 類直接申明一個線程t1,參數是這個線程執行的回調函數的地址,通過jion()方法阻塞主線程,直到t1線程執行結束為止。
?
???????? C++11支持Lambda表達式,因此一個新線程的回調函數也可以是有一個Lambda表達式的形式,但是注意如果使用Lambda表達式最好不要使用引用的方式,應該使用值傳遞的方式來訪問數據,在多線程中使用引用容易造成混亂。下面這個例子稍微復雜,創建了多個子線程,并使用了get_id()方法來獲取當前線程的id。
#include <thread>
#include <iostream>
#include <vector>
?
int main()
{
??? std::vector<std::thread> threads;
?
??? for(int i = 0; i < 5; ++i){
??????? threads.push_back(std::thread([](){
??????????? std::cout << "Hello from lamda thread " << std::this_thread::get_id() << std::endl;
??????? }));
??? }
?
??? for(auto& thread : threads){
??????? thread.join();
??? }
?
??? std::cout<<"Main Thread"<<"\t"<<std::this_thread::get_id()<<std::endl;
??? return 0;
}
運行結果:
上述代碼中,使用vector來存放每個線程,線程的回調函數通過Lambda表達式產生,注意后面join的使用方式。
?
可以通過sleep_for來使線程睡眠一定的時間:
#include <thread>
#include <iostream>
#include <mutex>
using namespace std;
?
int main()
{
??? std::mutex m;
??? thread t1([&m]()
??? {
??????? std::this_thread::sleep_for (chrono::seconds(10));?
??????? for(int i=0;i<10;i++)?
??????? ?{?????
??????????? m.lock();?
??????????????? cout <<? "In t1 ThreadID : " << std::this_thread::get_id() << ":" << i << endl;?????????
??????????? m.unlock ();?
??????? }?
??? } );
?
??? thread t2([&m]()?
??? {??????????
??? ??? std::this_thread::sleep_for (chrono::seconds(1));?
??? ??? for(int i=0;i<10;i++)?
??? ??? {?????????
??? ??????? m.lock ();?
??? ??????????? cout <<? "In t2 ThreadID : " << std::this_thread::get_id() << ":" << i << endl;?????????
??? ??????? m.unlock();?
??? ??? }?
??? } );?
??? t1.join();?????
??? t2.join();?????
?
??? cout<<"Main Thread"<<endl;
?
??? return 0;
}
運行結果:
可以看出,由于線程t1睡眠的時間較長,t2先執行了。
延時有這幾種類型:nanoseconds、microseconds、milliseconds、seconds、minutes、hours。
在使用多線程的程序中操作共享數據的時候一定要小心,由于線程的亂序執行,可能會得到意想不到的結果。通過下面的程序來看:
#include <thread>
#include <iostream>
#include <vector>
#include <mutex>
?
struct Counter {
??? std::mutex mutex;
??? int value;
?
??? Counter() : value(0) {}
?
??? void increment(){
?????? // mutex.lock();??????????????? 【1】表示沒有使用鎖
??????? ++value;
?????? // mutex.unlock();????????????? 【1】
??? }
?
??? void decrement(){
??????? mutex.lock();
??????? --value;
??????? mutex.unlock();
??? }
};
?
int main(){
??? Counter counter;
?
??? std::vector<std::thread> threads;
?
??? for(int i = 0; i < 5; ++i){
??????? threads.push_back(std::thread([&](){
??????????? for(int i = 0; i < 10000; ++i){
??????????????? counter.increment();
??????????? }
??????? }));
??? }
?
??? for(auto& thread : threads){
??????? thread.join();
??? }
?
??? std::cout << counter.value << std::endl;
?
??? return 0;
}
運行結果:
【1】
運行結果:(使用了鎖)
說明:由于創建線程是使用lambda表達式,并使用引用的方式訪問counter這個變量,當沒有使用lock來保護的時候(情況【1】),執行的結果可能不像預期的5000(程序的意思是每個線程使counter中的value自加1000次,5個線程運行結束的時候應該是5000),當沒有使用鎖的時候自加的操作可能被其他線程打斷,因此結果可能會小于5000。
?
?
make it simple, make it happen轉載于:https://www.cnblogs.com/lvdongjie/p/4487723.html
總結
以上是生活随笔為你收集整理的C++11 多线程 基础的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 分布式系列四: HTTP及HTTPS协议
- 下一篇: 【T-SQL系列】新的排序函数