C++11 多線程相關知識的學習

C++多線程類Thread(C++11)

  • C++11中std命名空間將Boost庫中的Thread加入,Boost的多線程從準標準變為標準,這里將其用法整理復習,以demo的形式復習,還是喜歡看我自己寫的東西,符合我的個人邏輯
  • 頭文件為#include<thread>,通過std::thread應用。就以Hello thread開始吧,需要注意的是1,join()函數和detach()函數的區別,2,數據同步操作mutex(需包含include<mutex>):互斥鎖

1、??普通函數多線程調用

(1)無參數函數

#include <thread>
#include <iostream>void hello_thread() {std::cout << "Hello Thread!" << std::endl;
}int main() {std::thread t1(hello_thread);  t1.join();  // 主線程等待子線程執行結束之后,才會執行下一步的操作std::cout << "Main here" << std::endl;getchar();return 0;
}

(2)有參數函數

#include <thread>
#include <iostream>using namespace std;int msum(int a, int b) {int c = a + b;cout << a << " + " << b << " = " << c << endl;return c;
}int main() {std::thread t1(msum,1,2);t1.join();  // 主線程等待子線程執行結束之后,才會執行下一步的操作std::cout << "Main here" << std::endl;getchar();return 0;
}

2、在類內部創建線程

(1)類內部函數為靜態函數

#include <thread>
#include <iostream>using namespace std;class HelloThread{public:static void hellothread(){cout << "Hello World, I‘m a thread " << endl;}static void start(){thread thread(hellothread);thread.join();}};int main(){HelloThread::start();getchar();return 0;
}
  • 在這里start()和hellothread()方法都必須是static方法。?

(2)在Singleton模式內部創建線程:?

3 、用類內部函數在類外部創建線程:

  • 非常普通的類,只是用多線程調用其內部的函數
#include <thread>
#include <iostream>using namespace std;class HelloWorld{public:void hello(int year){cout << "I am " << year << " years old!" << endl;}
};int main(){HelloWorld obj;thread thrd(&HelloWorld::hello,&obj,26);thrd.join();getchar();return 0;
}

?join()和detach()的區別:

  • join()的作用前面已經提到,主線程等待子線程結束方可執行下一步(串行),detach()是的子線程放飛自我,獨立于主線程并發執行,主線程后續代碼段無需等待。看看效果:

(1)join()

#include <thread>
#include <iostream>using namespace std;void hello_thread() {std::cout << "Hello Thread!" << std::endl;
}int msum(int a, int b) {int c = a + b;cout << a << " + " << b << " = " << c << endl;return c;
}int main(){thread t1(hello_thread);//主線程等待子線程運行結束之后才可以執行下一步t1.join();thread t2(msum,2,3);t2.join();//主線程代碼cout << "Main here " << endl;getchar();return 0;
}

(2)detach()

#include <thread>
#include <iostream>using namespace std;void hello_thread() {std::cout << "Hello Thread!" << std::endl;
}int msum(int a, int b) {int c = a + b;cout << a << " + " << b << " = " << c << endl;return c;
}int main(){thread t1(hello_thread);//主線程等待子線程運行結束之后才可以執行下一步t1.detach();thread t2(msum,2,3);t2.detach();//主線程代碼cout << "Main here " << endl;getchar();return 0;
}

?數據同步(線程同時操作一個數據的安全性):

  • 執行單個線程,上鎖、解鎖,維護了線程的安全性,防止線程之間交叉執行

#include <thread>
#include <iostream>
#include <mutex>
using namespace std;
std::mutex mt;
int data1 = 1;void addmethod(int a){mt.lock();data1 += a;cout << "add data = " << data1 << endl;mt.unlock();
}
void multi(int a){mt.lock();data1 *= a;cout << "multi data = " << data1 << endl;mt.unlock();
}
void hello_thread() {std::cout << "Hello Thread!" << std::endl;
}int msum(int a, int b) {int c = a + b;cout << a << " + " << b << " = " << c << endl;return c;
}int main(){thread t1(addmethod,2);thread t2(multi,2);t1.detach();t2.detach();getchar();return 0;
}

線程暫停

  • 從外部讓線程暫停,會引發很多并發問題,此處不做引申。這大概也是std::thread并沒有直接提供pause函數的原因。但有時線程在運行時,確實需要“停頓”一段時間怎么辦呢?可以使用std::this_thread::sleep_for或std::this_thread::sleep_until
#include <thread>
#include <iostream>
#include <mutex>
#include <chrono>
#include <ratio>
using namespace std;
std::mutex mt;void pausable(){//sleep 500毫秒this_thread::sleep_for(chrono::milliseconds(500));//sleep 到達指定的時間點this_thread::sleep_until(chrono::system_clock::now() + chrono::milliseconds(500));
}
int main(){std::thread thread1(pausable);thread1.join();return 0;
}

線程停止

  • 一般情況下當線程函數執行完成后,線程“自然”停止。但在std::thread中有一種情況會造成線程異常終止,那就是:析構。當std::thread實例析構時,如果線程還在運行,則線程會被強行終止掉,這可能會造成資源的泄漏,因此盡量在析構前join一下,以確保線程成功結束。
  • 如果確實想提前讓線程結束怎么辦呢?一個簡單的方法是使用“共享變量”,線程定期地去檢測該量,如果需要退出,則停止執行,退出線程函數。使用“共享變量”需要注意,在多核、多CPU的情況下需要使用“原子”操作。

參考鏈接

  • https://blog.csdn.net/ouyangfushu/article/details/80199140

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/447099.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/447099.shtml
英文地址,請注明出處:http://en.pswp.cn/news/447099.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

vscode vim 插件自定義配置

{"workbench.colorTheme": "Material Theme","files.defaultLanguage": "markdown", //新建文檔格式為markdown格式"vim.easymotion": true,"vim.leader": " ", // leader鍵"vim.useSystemClipbo…

C++11 explicit關鍵字的作用

explicit 在C中&#xff0c;explicit關鍵字用來修飾類的構造函數&#xff0c;被修飾的構造函數的類&#xff0c;不能發生相應的隱式類型轉換&#xff0c;只能以顯示的方式進行類型轉換。因為無參構造函數和多參構造函數本身就是顯示調用的。再加上explicit關鍵字也沒有什么意義…

c++ 指針的強制類型轉換

#include <iostream> using namespace std; class A { public:int i;int j;A(int n):i(n),j(n) { } }; int F2 (int,char *){return 1; }; int F1 (int){return 2; }; int main() {A a(100);int &r reinterpret_cast<int&>(a); //強行讓 r 引用 ar 200; …

C++11學習 virtual(虛函數)的用法

Virtual虛函數 在面向對象的C語言中&#xff0c;虛函數&#xff08;virtual function&#xff09;是一個非常重要的概念。因為它充分體現了面向對象思想中的繼承和多態性這兩大特性&#xff0c;在C語言里應用極廣。多態性&#xff1a;其含義就是多種形式&#xff1b;將具有繼承…

c++ const

函數名稱不單單是函數名 const 補充內容 還有 const 參數類型 函數后頭const 只能在成員函數如果const對象 但是我沒通過const成員函數 就會報錯

C++11學習 新特性之 “=default” 、“=delete”

文章目錄 1、 default 和delete 概述2、 類與默認函數3、 使用“delete”來限制函數生成4、 “default”使用范圍 1、 default 和delete 概述 default、delete 是C11的新特性&#xff0c;分別為&#xff1a;顯式缺省(告知編譯器生成函數默認的缺省版本)和顯式刪除(告知編譯器…

C++學習 優雅的實現對象到文件的序列化/反序列化 關鍵字serialize

需要使用到序列化場景的需求 在寫代碼的過程中&#xff0c;經常會需要把代碼層面的對象數據保存到文件&#xff0c;而這些數據會以各種格式存儲&#xff0e;例如&#xff1a;json&#xff0c;xml&#xff0c;二進制等等&#xff0e;二進制&#xff0c;相比json&#xff0c;xml…

C++代碼注釋詳解

常用注釋語法 注釋寫在對應的函數或變量前面。JavaDoc類型的多行注釋風格如下&#xff1a; /** * 這里為注釋. */ 一般注釋中有簡要注釋和詳細注釋&#xff0c;簡要注釋有多種標識方式&#xff0c;這里推薦使用brief命令強制說明&#xff0c;例如&#xff1a;/** * brief 這里…

段錯誤:SIGSEGV

SIGSEGV是在訪問內存時發生的錯誤&#xff0c;它屬于內存管理的范疇 SIGSEGV是一個用戶態的概念&#xff0c;是操作系統在用戶態程序錯誤訪問內存時所做出的處理。 當用戶態程序訪問&#xff08;訪問表示讀、寫或執行&#xff09;不允許訪問的內存時&#xff0c;產生SIGSEGV。 …

web3 0.2.x 和 1.x.x版本之間的差異

版本差異 單位轉換 0.2.x web3.fromWei(13144321,ether) 1.x.x web3.utils.fromWei(13144321,ether)1.0以后的版本使用了大量的Promise&#xff0c;可以結合async/await使用&#xff0c;而0.20版本只支持回調函數

如何提高閱讀源碼的能力并且手撕源碼

怎么有效的手撕代碼呢&#xff1f; 把代碼跑起來把代碼一個片段拿出來使用畫出代碼運行的流程圖一行一行的搬運在看源碼的情況下寫出類似的demo

并發和并行的區別簡單介紹

并發和并行 并發是關于正確有效地控制對共享資源的訪問 同時完成多個任務。在開始處理其他任務之前&#xff0c;當前任務不需要完成。并發解決了阻塞發生的問題。當任務無法進一步執行&#xff0c;直到外部環境發生變化時才會繼續執行。最常見的例子是I/O&#xff0c;其中任務…

手撕源碼 alloc

怎么有效的手撕代碼呢&#xff1f; gnu gcc 2.9 的 內存池 把代碼跑起來把代碼一個片段拿出來使用畫出代碼運行的流程圖一行一行的搬運在看源碼的情況下寫出類似的demo 第三步&#xff1a; 第五步: // 這個頭文件包含一個模板類 allocator&#xff0c;用于管理內存的分配、…

Algorand的共識協議及其核心的優勢

Algorand 設計的初衷 Algorand 想解決的核心問題是&#xff1a;去中心化網絡中低延時&#xff08;Latency&#xff09;和高置信度&#xff08;Confidence&#xff09;之間的矛盾。其中&#xff0c;延時指從發起交易到確認交易所需要的時間&#xff1b;置信度指的是發出的交易不…

手撕源碼 SQL解析器 sqlparser

怎么有效的手撕代碼呢&#xff1f; 源代碼&#xff1a;https://github.com/hyrise/sql-parser 把代碼跑起來把代碼一個片段拿出來使用畫出代碼運行的流程圖一行一行的搬運在看源碼的情況下寫出類似的demo

針對Algorand所使用的密碼相關技術細節進行介紹

關鍵概念 VRF: 可驗證隨機函數。簡單來說是&#xff1a;vrf,Proof VRF(sk,seed)&#xff0c;sk為私鑰&#xff0c;seed為隨機種子&#xff1b;通過Verify(proof,pk,seed)驗證vrf的合法性。cryptographic sorition: 根據用戶本輪的VRF值&#xff0c;自身的權重以及公開的區塊鏈…

內存池的實現1 :重載

#ifndef KSTD_ALLOCATOR_H_ #define KSTD_ALLOCATOR_H_// 這個頭文件包含一個模板類 allocator&#xff0c;用于管理內存的分配、釋放&#xff0c;對象的構造、析構 // 暫不支持標準庫容器 todo::支持萃取#include <new> // placement new #include <cstddef>…

對于Algorand的介紹

介紹 Algorand具有能耗低、效率高、民主化、分叉概率極低、可拓展性好等優點&#xff0c;旨在解決現有區塊鏈項目存在的“不可能三角”&#xff08;高度可擴展的、安全的、去中心化&#xff09;問題。Algorand由MIT教授、圖靈獎得主Silvio Micali發起&#xff0c;擁有MIT區塊鏈…

內存池的實現2 類專用的內存適配器

B類增加了嵌入指針 #include<new> #include<ctime> #include<iostream> #include<cstdio> class A { public:A() {printf("next%p\n", next);};static void* operator new(size_t size);static void operator delete(void* phead);static i…