pthread.h相関関数使用方法集錦のスレッド操作

6636 ワード

前言
pthread(POSIX thread)は、pthreadと略称され、スレッドのPOSIX規格であり、クラスUnixオペレーティングシステム(Unix、Linux、Mac OS Xなど)では、いずれもpthreadをオペレーティングシステムのスレッドとして用いている.そのプログラミング標準のヘッダファイルとして,本稿では,中の常用関数の意義と使用方法を検討する.
スレッド
pthread_create pthread_createはUNIX環境作成スレッド関数です.合計4つのパラメータ:
  • 最初のパラメータはスレッド識別子を指すポインタであり、type:pthread_t*
  • スレッド属性
  • を設定するための2番目のパラメータ
  • の3番目のパラメータはスレッド実行関数の開始アドレスであり、type:(void*)(*)(void*)
  • 4番目のパラメータは実行関数のパラメータで、type:void *
  • パラメータなし関数pthread_createスレッドがパラメータ関数なしを実行するdemoを作成します.
    #include 
    #include 
    
    using namespace std;
    
    //       : void* (*)(void*)
    void* test(void *ptr){
        cout << "hello world." << endl;
    }
    
    int main()
    {
        pthread_t tid; //     id typedef unsigned
        pthread_create(&tid, NULL, test, NULL); //     
        pthread_join(tid, NULL);
    }
    

    パラメータ関数pthread_createは単一のポインタのみをサポートし、1つのパラメータしか送信できません.複数のパラメータを渡す場合は、構造体形式にカプセル化します.
    #include 
    #include 
    #include 
    
    using namespace std;
    
    struct Param{
        string name;
        int age;
    };
    
    void* param_test(void* p){
        Param *param = (Param*)p;
        cout << "hello " << param->name << endl;
        cout << "age = " << param->age << endl;
    }
    
    int main()
    {
        pthread_t tid;
        Param *ptr = new Param();
        ptr->name = "pthread";
        ptr->age = 20;
        pthread_create(&tid, NULL, param_test, ptr);
        pthread_join(tid, NULL);
    }
    

    クラスメンバー関数
    クラスメンバー関数を呼び出す方法は少し複雑で、別の関数パッケージが必要です.関数パラメータはクラスインスタンスポインタに明示的に入力され、その後、パラメータ付き関数を呼び出す方法と似ています.
    #include 
    #include 
    #include 
    
    using namespace std;
    
    class PthreadClass{
        public:
            void say_hello(){
                cout << "hello world" << endl;
            }
    };
    
    //           
    void* class_test(void *p){
        PthreadClass *ptr = (PthreadClass*)p;
        //     
        ptr->say_hello();
    }
    
    int main()
    {
        PthreadClass *ptr = new PthreadClass();
        pthread_t tid;
        pthread_create(&tid, NULL, class_test, ptr);
        pthread_join(tid, NULL);
    }
    

    pthread_join pthread_joinは、1つのスレッドの終了を待つために使用され、スレッド間で同期された動作、2つのパラメータがあります.
  • 最初のパラメータはスレッド識別子、すなわちスレッドID、type:pthread_t
  • である.
  • 第2のパラメータretvalは、スレッドの戻り値を格納するためにユーザ定義ポインタであり、type: void**
  • .
    #include 
    #include 
    
    using namespace std;
    
    class PthreadClass{
        public:
            void say_hello(){
                cout << "hello world" << endl;
            }
    };
    
    int retval = -1;
    void* class_test(void *p){
        PthreadClass *ptr = (PthreadClass*)p;
        ptr->say_hello();
        retval = 0;
        return (void*)&retval;
    }
    
    int main()
    {
        PthreadClass *ptr = new PthreadClass();
        pthread_t tid;
        pthread_create(&tid, NULL, class_test, ptr);
        /**
         *     
         *   ,    pthread_join,                      
         */
        void *retval;
        pthread_join(tid, &retval);
        cout << *(int*)retval << endl;
    }
    

    pthread_detach
    スレッドの作成のデフォルトのステータスはjoinableです.スレッドが実行を終了してもjoinされていない場合、そのステータスはプロセス内のZombie Processに似ています.つまり、一部のリソースが回収されていない(ステータスコードを終了する)ので、スレッドの作成者はpthread_joinでスレッドの実行が終了するのを待って、スレッドの終了コードを得ることができます.リソースを回収します(wait,waitpidに似ています).しかし、pthread_joinを呼び出すと、スレッドが実行終了しない場合、呼び出し元がブロックされ、Webサーバでプライマリ・スレッドが新しく来たリンクごとにサブスレッドを作成して処理する場合、プライマリ・スレッドはpthread_を呼び出すことを望んでいない場合があります.joinでブロック(処理を継続してから来るリンクのため)すると、サブスレッドにコードpthread_datachを追加してブロックから離脱することができ、このときサブスレッド状態はdetachedであり、実行終了後に自動的にリソースが解放される.pthread_detachパラメータは1つのみです.
  • 最初のパラメータはスレッド識別子、すなわちスレッドID、type:pthread_t
  • である.
    #include 
    #include 
    #include 
    
    using namespace std;
    
    void* test(void *p){
        sleep(1000);
    }
    
    int main()
    {
        pthread_t tid;
        pthread_create(&tid, NULL, test, NULL);
        pthread_detach(tid);
        for(int i = 0; i < 1000; i ++){
            sleep(1);
            cout << "sleep " << i << " second." << endl;
        }
    }
    

    ここではpthread_detachを使用するとtestsleep内に詰まることなくforサイクルに入り、pthread_joinを使用するとtest関数の実行が完了するまで待機します.
    pthread_self pthread_self関数にはパラメータがなく、現在のスレッドidを取得する役割を果たします.
    
    #include 
    #include 
    #include 
    
    using namespace std;
    
    void* test(void *p){
        cout << 'child thread: ' << pthread_self() << endl;
    }
    
    int main()
    {
        pthread_t tid;
        pthread_create(&tid, NULL, test, NULL);
        pthread_detach(tid);
        cout << 'main thread: ' << pthread_self() << endl;
        for(int i = 0; i < 1000; i ++){
            sleep(1);
        }
    }
    

    以上のコードは、メインスレッドとサブスレッドの異なるスレッドidを出力します.
    main thread: 1
    child thread: 2
    

    pthread_once pthread_onceはマルチスレッド環境で1回のみ実行され、マルチスレッド環境で1回のみ実行する必要がある操作をpthread_onceに渡すと、スレッドは安全に1回のみ実行されます.pthread_onceには2つのパラメータがあります.
  • の最初のパラメータはpthread_once_t変数であり、識別子に相当するtype:pthread_once_t
  • である.
  • 第2パラメータは無パラメータ関数ポインタ、type:void(*func)(void)
  • 以下の例では、once_runは1回のみ実行されるが、実行されるたびに結果が異なる場合があり、once_runはスレッド1で実行される場合もあり、スレッド2で実行される場合もある.
    
    #include
    #include
    #include 
    using namespace std;
    
    pthread_once_t once = PTHREAD_ONCE_INIT;
    
    void once_run(void)
    {
        cout<

    出力:
    thread 2 enter
    once_run in thread 2
    thread 2 return
    thread 3 enter
    thread 3 return
    

    pthread_cancel cancel信号を指定したスレッドに送信します.パラメータスレッド識別子は1つしかありません.タイプはpthread_tです.使い方は簡単です.ここではあまり紹介しません.原理を理解する学生はlinuxの下でmanコマンドでもっと知ることができます.
    man pthread_cancel
    

    pthread_kill
    あるスレッドに信号を渡すには、作成したスレッドでsignal(SIGKILL,sig_handler)関数を使用して信号を処理する必要があります.スレッドにSIGQUITを送信したが、スレッドがsignal処理関数を実装していない場合、プロセス全体が終了します.pthread_killの2つのパラメータ:
  • 最初のパラメータはスレッドマーカー、type:pthread_t
  • の2番目のパラメータはLinuxで定義された信号であり、type:int
  • テキストリンク