環境
- wsl ubuntu 18.04 LTS
- gcc version 7.5.0
其實這個并不重要,就圖個儀式感,hh,不過必須是在Linux系統下實作的,windows平臺是不可以的,c++在windows平臺實作多執行緒不是使用的這個庫
時間片輪轉
代碼
#include <iostream>
#include <thread>
using namespace std;
void func(int i,int times){
puts("thread id: ");
for(int i=0;i<=times;i++)
printf("%d ",i);
cout<<endl;
}
int main() {
thread th[5];
for(int i=0;i<5;i++)
th[i]=thread(func,i,40);// 這里的times引數最好大一點,才能看出效果
// thread 傳入的引數為:函式指標,函式的各個引數
for(int i=0;i<10;i++)
th[i].join();
return 0;
}
編譯
g++ main.cpp -o main -lpthread #這里的 -lpthread 是鏈接thread庫,很重要,不添加的話會編譯不通過
這樣重復運行程式,會發現每次的輸出不一樣,這就是不同執行緒時間片輪轉的結果
執行緒同步
代碼
#include <iostream>
#include <thread>
using namespace std;
int n;
void func() {
for (int i = 0; i < 10000; i++)
n++;
}
int main() {
thread th[100];
for (thread &it : th)
it = thread(func);
for (thread &it : th)
it.join();
cout << n << endl;
return 0;
}
按照邏輯應該輸出 1000000,但是實際上并沒有,往往小于此值,因為各個執行緒出現了同時訪問n的情況,所以針對這種情況,我們需要用到互斥鎖
為什么不能使用 std::atomic?
在mutex庫中常用的std::mutex和std::atomic都可實作互斥訪問,我們常常為了追求更高的效率,會用std::atomic而不是std::mutex,并且std::atomic的使用更加方便易懂,但是如果我們要用std::atomic和std::queue來實作訊息佇列,是不可行的,接下來我會根據我所找到的資料,做一個大致的解釋,
-
先放一個stackoverflow上大佬的大致解釋
A)
atomic <queue <T>> fifo;B)
queue <atomic <T>> fifo;兩種方式都是不可以的,A甚至不能正確編譯,B可以實作原子操作的讀和寫,但是無法實作
queue的例如pop(), push()等操作 -
首先,
atomic<T> var中,T的型別必須是TriviallyCopyable(翻譯過來可以理解成拷貝不變),那么是TriviallyCopyable呢?檔案如下Scalar types標量型別
- 標量型別(Scalar type)是相對復合型別(Compound type)來說的:標量型別只能有一個值,而復合型別可以包含多個值,復合型別是由標量型別構成的,
- 在C語言中,整數型別(int、short、long等)、字符型別(char、wchar_t等)、列舉型別(enum)、小數型別(float、double等)、布爾型別(bool)都屬于標量型別,一份標量型別的資料只能包含一個值
- 結構體(struct)、陣列(array)、字串(string)都屬于復合型別,一份復合型別的資料可以包含多個標量型別的值,也可以包含其他復合型別的值,
-
rivially copyable classes, i.e. classes satisfying following requirements拷貝不變類,也就是滿足以下條件:
- At least one copy constructor, move constructor, copy assignment operator, or move assignment operator is eligible必須有一個拷貝建構式,或者移動建構式,或者拷貝賦值運算子,或者移動賦值運算子
- Every eligible copy constructor (if any) is trivial每個復制建構式均為平凡或棄置的
- Every eligible move constructor (if any) is trivial每個移動建構式均為平凡或棄置的
- Every eligible copy assignment operator (if any) is trivial每個復制賦值運算子均為平凡或棄置的
- Every eligible move assignment operator (if any) is trivial每個移動賦值運算子均為平凡或棄置的
- Has a trivial non-deleted destructor平凡而未棄置的解構式
-
Arrays of TriviallyCopyable objects可平凡復制 (TriviallyCopyable) 物件的陣列
(補充:什么叫平凡類函式呢?簡單點講就是如果類T滿足:1. 函式不是用戶提供的,即他是隱式定義或者預置的;2. T沒有虛成員函式;3. T沒有虛基類;4. 為
T的每個直接基類選擇的復制建構式都是平凡的;5. 為 T 的每個型別別(或型別別陣列)的非靜態成員選擇的復制建構式都是平凡的)
所以講了一大堆,就是一個意思,用std::atomic和std::queue來實作訊息佇列,是不可行的!
實作對queue的操作保護只能是使用mutex!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/308179.html
標籤:C++
上一篇:PRCfailed;HTTP413,HowcanIseparatepushcommit
下一篇:SSA
