1. 程式人生 > >使用C++11進行多執行緒歸併排序:std::thread

使用C++11進行多執行緒歸併排序:std::thread

相對於使用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; }