[Boostベース]同時プログラミング-Threadマルチスレッド(一)

6886 ワード

同時プログラミング
同時プログラミング:C++には言語レベルの同時サポートはありません.C++が誕生してからスレッドなどの同時操作の概念が現れたからです(POSIXスレッド標準制定と1955年).しかし、現在ではマルチCPU、マルチコアを持つコンピュータが大量に登場するにつれて、C++特にC++標準が同時操作を定義していない規範は時代遅れになっている.同時プログラミングは広範な話題であり、複雑な技術でもある.
Boostには、同時プログラミング用の2つのコンポーネントがあります.まずtheadライブラリ:C++に移植可能なスレッド処理能力を追加しました.次に、シリアルポート、ネットワーク通信を処理し、C++標準の下位通信ライブラリになることが期待されるプリアンブルモードを使用した、同期および非同期IO操作のための強力なライブラリであるasioがあります.
threadマルチスレッド
threadライブラリはC++のためにスレッド処理の能力を増加させ、簡明で明確なスレッド、反発量などの概念を提供し、マルチスレッドアプリケーションを簡単に作成することができます.threadライブラリも高度に移植されており、最も広範なwindowsやPOSIXスレッドの使用をサポートしており、作成したコードを変更する必要がなくwindows、UNIXなどのオペレーティングシステム上で実行することができます.ここではthreadライブラリの使用についてのみ説明し、マルチスレッドプログラムの作成方法については説明しません.それは別の本が必要です.
A.時間機能
マルチスレッドプログラミングではタイムアウト処理がしばしば用いられ,時間を表す概念が必要である.threadライブラリ直接利用date_timeライブラリは時間のサポートを提供し、millisec/millisiseconds、microsec/microssec/microssecondなどの時間長を使用してタイムアウトの時間を表すか、ptimeで特定の時点を表すことができます.
B.反発量
反発量は、スレッドプログラミングにおいて複数のスレッドが共有リソース(または臨界領域)を同時に操作することを防止するためのスレッド同期のための手段である.1つのスレッドが反発量をロックすると、共有リソースにアクセスするには、他のスレッドが反発量をロック解除するのを待たなければなりません.theadは、7つの反発量タイプを提供し、それぞれ:
  • 1.mutex:独占式の反発量は、最も簡単で最もよく使われる反発量のタイプである.
  • 2.try_mutex:彼はmutexの同義語で、以前のバージョンと互換性を持つために
  • を提供しています.
  • 3.timed_mutex:排他的な反発量でもありますが、タイムアウトロック機能を提供します.
  • 4.recursive_mutex:再帰反発量、複数回ロックでき、対応する複数回ロックを解除しなければならない.
  • 5.recursive_try_mutex:recursiveですmutexの同義語は、以前のバージョンと互換性を持つために提供されています.
  • 6.recursive_timed_mutex:再帰的反発量でもあり、基本機能はrecursive_と同じです.mutexですが、タイムアウトロック機能
  • が提供されています.
  • 7.shared_mutex:multiple-reader/single-writer型の共有反発量(読み書きロックとも呼ばれる)
  • メンバー関数は、次のようになります.
  • 1.lock()は、反発量の所有権を得るまでスレッドがブロックするための待ち時間(すなわちロック)
  • である.
  • 2.try_lock()は反発量をロックしようと試み、ロックがtrueに正常に戻るとfalseに戻り、ブロックされていない
  • である.
  • 3.unlock()スレッドが共有リソースを使用した後、unlock()を使用して反発量のロックを解除する必要があります.
  • 4.time_lock()はtimed_のみmutexとrecursive_timed_mutex、その行為はlock()とtry_を結合した.lock()は、ブロックが一定の時間待って反発量をロックしようとし、時間が経ってもロックされている場合falseを返す.待ち時間は、絶対時間(1つのUTC時点)でもよいし、現在からの相対時間(時間長)
  • でもよい.
    C.スレッドオブジェクト
    threadクラスはthreadライブラリのコアクラスであり、スレッドオブジェクトの起動と管理を担当し、概念と操作の面でPOSIXスレッドとよく似ている.threadオブジェクトを使用する場合は、boost::noncopyableから継承されていませんが、thread内部ではコピーコンストラクタと付与操作がプライベートとして宣言されており、付与またはコピー構造はできません.threadは特別なメカニズムで転送の意味をサポートするため、スレッドを作成するファクトリ関数を作成し、threadの作成の詳細をカプセル化し、threadオブジェクトを返すことができます.
    D.スレッドの作成
    ある程度、スレッドはプロセス内の別の空間で実行される関数であるため、スレッドの作成にはthreadオブジェクトを渡す必要があります.パラメータのない呼び出し物(関数または関数オブジェクト)であり、スレッドの実行のためにoperator()を持つ必要があります.呼び出し可能なものが無パラメータでない場合、threadの構造関数は、呼び出しが発生したときに関数に渡されるようにコピーされた必要なパラメータを直接伝達することもサポートします.これは、従来のvoid*を使用してパラメータを伝達するよりも、非常に便利なリロード構造関数です.threadの構造関数は、通常十分な9つのパラメータの伝達をサポートします.パラメータを渡すときは、threadはパラメータのコピーを使用するため、呼び出し可能なものとパラメータタイプの両方がコピーをサポートする必要があることに注意してください.スレッド参照値に渡すにはrefライブラリを使用してパッケージする必要があります.また、参照されたオブジェクトがスレッド実行中に常に存在することを保証する必要があります.そうしないと、未定義の動作が発生します.
    #pragma  once 
    #include <boost/thread.hpp>  
    #include <boost/bind.hpp>   
    #include <string>
    #include <conio.h>   
    using namespace boost;
    //A.     
    void test1()
    {        
    	this_thread::sleep(posix_time::seconds(10));
    	std::cout<<"sleep 2 sconds"<<std::endl;
    	//                ,thread              system_time,  posix_time::ptime    :typedef boost::posix_time::ptime system_time;。      get_system_time()  ,   microsec_clock         UTC   。
    	boost::system_time st=get_system_time();
    	printf("system_time: %d
    ",st); } //B. // , 。 template <typename T> class basic_atom : boost::noncopyable { private: T n; typedef mutex mutex_t;// mutex_t mu; public: basic_atom(T x=T()) : n(x){}// T operator++()// { mutex_t::scoped_lock lock(mu);// return ++n; } operator T(){return n;}// }; void test2() { //basic_atom , , ,; 。 basic_atom<int> x(2); std::cout<<++x<<std::endl; //mutex mutex mu; // try { mu.lock();// std::cout<<"some operations"<<std::endl;// // 3 mu.unlock(); // } catch(thread_interrupted&)// try-catch { mu.unlock(); std::cout<<"unlock"<<std::endl; } // mutex , ; thread RAII lock_guard , 。 , , , , 。mutex scoped_lock scoped_try_lock lock_guard , lock() try_lock()。 : // mutex mud; // mutex::scoped_lock lock(mud); // std::cout<<"some operations"<<std::endl; } //D. mutex muIO;//io , ; , void printing(basic_atom<int>& x,const std::string& str) { for (int i=0;i<5;i++) { mutex::scoped_lock lock(muIO);// io std::cout<<str<<++x<<std::endl; } } void test3() { //1. // thread , ,thread start(),begin() 。 basic_atom<int> x;// // thead thread(printing,ref(x),"hello ");// thread(printing,ref(x),"boost ");// ref this_thread::sleep(posix_time::seconds(2));// 2 // , sleep() , mian() return , 。 “ ” , , 。 //2.join timed_join //thread joinable() thread 。 joinable() true, join() timed_join() 。 basic_atom<int> y; thread t1(printing,ref(y),"helloy"); thread t2(printing,ref(y),"boosty"); t1.timed_join(posix_time::seconds(1));// 1 t2.join();// t2 , //3. // detach() thread , thread , thread t3(printing,ref(x),"helloz");// t3.detach();// , if (t3.joinable()) // false //joinable() thread 。 std::cout<<"t3 is joinable"<<std::endl; // // thread , , , 。 thread ,thread , , , 。eg:thread(printing,ref(x),"hello ");// //4. bind function // thread , 。 bind function :bind , function bind , 。 boost::thread t4(boost::bind(printing,ref(x),std::string("thread")));//bind boost::function<void()> fun=boost::bind(printing,ref(x),std::string("mutex")); thread t5(fun);// function } void test(char t) { std::cout<<"press key====="<<t<<std::endl; switch (t) { case '1':test1();break; case '2':test2();break; case '3':test3();break; case 27: case 'q':exit(0);break; default: std::cout<<"default "<<t<<std::endl;break; } } void main() { while(1) test(getch()); }