使用C++11進行多執行緒歸併排序:std::thread
阿新 • • 發佈:2019-02-04
相對於使用pthread來說,c++的標準庫對多執行緒的程式設計封裝的非常好,使用起來有如下幾個優勢:
1: 可以直接傳遞引數給函式,而不需要將它封裝到一個結構體再轉換成為void*傳入。
2 :對於目標函式的要求不再是void*的返回型別,這樣如果要使用一些內建的函式,就不需要進行單獨封裝成void*型別。
======================================================
此外,編寫下面的程式發現了以下幾個要注意的地方.
1: 首先,如果目標函式是模板,那麼必須要顯示模板化,因為編譯器不知道目標函式的引數,thread函式會將它收到的引數拷貝 之後轉發給目標函式。所以編譯的時候目標函式的型別不確定,這樣就會導致出錯。
2: 其次,如該函式引數裡面含有引用,那麼必須要採用ref,因為thread是拷貝引數然後轉發,所以必須如該利用std::ref,那麼獲取的引數就是拷貝的引用,這也會引起錯誤。
3: 最後需要指出,因為thread預設是joinable的,所以不能在thread結束之前就結束呼叫它的執行緒。必須要加join.否則執行時會出現terminate without an active exception.
#include <iostream>
#include <thread>
#include <fstream>
#include <string>
#include <vector>
#include <cstdlib>
#include <typeinfo>
#include <algorithm>
#include "unistd.h"
using namespace std;
#define NUM_THREADS 5
template<typename T>
vector<T> read_file(string filename)
{
ifstream file(filename);
int each_element;
vector<int> data;
if (file){
while(file>>each_element) {
data.push_back(each_element);
}
}
return data;
}
template<typename T>
void my_merge(T& arr,int l,int mid,int r)
{
size_t i = 0,j = 0,k = l;
size_t bound1 = mid-l,bound2 = r-mid;
T first;
T second;
for(size_t i = l;i!=mid;++i){first.push_back(arr[i]);}
for(size_t i = mid;i!=r;++i){second.push_back(arr[i]);}
while(i<bound1 & j<bound2)
{
if (first[i]<second[j]){ arr[k++] = first[i++];}
else{arr[k++] = second[j++];}
}
while (i<bound1){arr[k++] = first[i++]; }
while (j<bound2){arr[k++] = second[j++];}
}
template<typename T>
void merge_sort(size_t l,size_t h,T& arr)// merge the arr[l]->arr[h-1]
{
if (h-l < 5) {sort(arr.begin()+l,arr.begin()+h);
return ;}
size_t mid = (l+h)>>1;
thread sub_thread1(merge_sort<T>,l,mid,ref(arr));
thread sub_thread2(merge_sort<T>,mid,h,ref(arr));
sub_thread1.join();
sub_thread2.join();
my_merge(arr,l,mid,h);
}
int main()
{
vector<string> data = {"azcd","afgh","z","hijk","sdf","hlus"};
thread merge_(merge_sort<decltype(data)>,0,data.size(),ref(data));
merge_.join();
for(const auto &x : data){cout<<x<<endl;}
return 0;
}