Linux Cプログラミング——マルチスレッド


スレッドは、コンピュータ内で独立して実行される最小単位であり、実行時に少ないシステムリソースを占有します.マルチプロセスに比べて、マルチプロセスにはマルチプロセスが備えていないいくつかの利点があります.最も重要なのは、マルチスレッドにとって、マルチプロセスよりもリソースを節約できることです.
1、スレッド作成
Linuxでは、新しいスレッドは元のプロセスではなく、システムが1つのシステムを通じてclone()を呼び出す.このシステムcopyは、元のプロセスと全く同じプロセスを実行し、このプロセスでスレッド関数を実行します.
Linuxでは、関数pthread_create()の関数を使用してスレッドの作成を行います.
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);

次のようになります.
  • threadはpthread_を表すtタイプのポインタ;
  • attrは、スレッドのいくつかの属性を指定するために使用される.
  • start_routineは、スレッド呼び出し関数である関数ポインタを表します.
  • argは、スレッド呼び出し関数に渡されるパラメータを表す.

  • スレッドの作成に成功すると、関数pthread_create()は0を返し、戻り値が0でないとスレッドの作成に失敗します.スレッドの属性は、構造体pthread_attr_tにおいて定義される.
    スレッドの作成手順は次のとおりです.
    #include <stdio.h>
    #include <pthread.h>
    #include <unistd.h>
    #include <malloc.h>
    
    void* thread(void *id){
            pthread_t newthid;
    
            newthid = pthread_self();
            printf("this is a new thread, thread ID is %u
    "
    , newthid); return NULL; } int main(){ int num_thread = 5; pthread_t *pt = (pthread_t *)malloc(sizeof(pthread_t) * num_thread); printf("main thread, ID is %u
    "
    , pthread_self()); for (int i = 0; i < num_thread; i++){ if (pthread_create(&pt[i], NULL, thread, NULL) != 0){ printf("thread create failed!
    "
    ); return 1; } } sleep(2); free(pt); return 0; }

    上記コードでは、pthread_self()の関数が用いられ、この関数は、本スレッドのスレッドIDを取得する役割を果たす.メイン関数のsleep()は、スレッドの実行を完了させるために、メインプロセスを待機状態にするために使用される.最終的な実行効果は次のとおりです.
    ではargを用いてサブスレッドにパラメータを渡すにはどうすればよいのでしょうか.その具体的な実現は以下の通りである.
    #include <stdio.h>
    #include <pthread.h>
    #include <unistd.h>
    #include <malloc.h>
    
    void* thread(void *id){
            pthread_t newthid;
    
            newthid = pthread_self();
            int num = *(int *)id;
            printf("this is a new thread, thread ID is %u,id:%d
    "
    , newthid, num); return NULL; } int main(){ //pthread_t thid; int num_thread = 5; pthread_t *pt = (pthread_t *)malloc(sizeof(pthread_t) * num_thread); int * id = (int *)malloc(sizeof(int) * num_thread); printf("main thread, ID is %u
    "
    , pthread_self()); for (int i = 0; i < num_thread; i++){ id[i] = i; if (pthread_create(&pt[i], NULL, thread, &id[i]) != 0){ printf("thread create failed!
    "
    ); return 1; } } sleep(2); free(pt); free(id); return 0; }

    最終的な実行効果は、次の図のようになります.
    プライマリ・プロセスが早期に終了した場合、どのような状況になりますか?次のコードに従います.
    #include <stdio.h>
    #include <pthread.h>
    #include <unistd.h>
    #include <malloc.h>
    
    void* thread(void *id){
            pthread_t newthid;
    
            newthid = pthread_self();
            int num = *(int *)id;
            printf("this is a new thread, thread ID is %u,id:%d
    "
    , newthid, num); sleep(2); printf("thread %u is done!
    "
    , newthid); return NULL; } int main(){ //pthread_t thid; int num_thread = 5; pthread_t *pt = (pthread_t *)malloc(sizeof(pthread_t) * num_thread); int * id = (int *)malloc(sizeof(int) * num_thread); printf("main thread, ID is %u
    "
    , pthread_self()); for (int i = 0; i < num_thread; i++){ id[i] = i; if (pthread_create(&pt[i], NULL, thread, &id[i]) != 0){ printf("thread create failed!
    "
    ); return 1; } } //sleep(2); free(pt); free(id); return 0; }

    このとき、メインプロセスが早期に終了すると、プロセスはリソースを回収し、スレッドは実行を終了し、実行結果は次のようになります.
    2、スレッドの保留
    上記の実装では、メインスレッドが各サブスレッドの実行が完了してから終了するのを待つことができるように、free()関数を用いたが、Linuxのマルチスレッドでは、pthread_join()関数を用いて他のスレッドを待つようにしてもよい.
    int pthread_join(pthread_t thread, void **retval);

    関数pthread_join()は、スレッドの終了を待つために使用され、その呼び出しは保留される.
    1つのスレッドでは、1つのスレッドがpthread_join()を使用して終了を待つことしかできません.
    次のコードに示すように、各サブスレッドの終了をメインスレッドで待つ必要がある場合.
    #include <stdio.h>
    #include <pthread.h>
    #include <unistd.h>
    #include <malloc.h>
    
    void* thread(void *id){
            pthread_t newthid;
    
            newthid = pthread_self();
            int num = *(int *)id;
            printf("this is a new thread, thread ID is %u,id:%d
    "
    , newthid, num); free(3); printf("thread %u is done
    "
    , newthid); return NULL; } int main(){ int num_thread = 5; pthread_t *pt = (pthread_t *)malloc(sizeof(pthread_t) * num_thread); int * id = (int *)malloc(sizeof(int) * num_thread); printf("main thread, ID is %u
    "
    , pthread_self()); for (int i = 0; i < num_thread; i++){ id[i] = i; if (pthread_create(&pt[i], NULL, thread, &id[i]) != 0){ printf("thread create failed!
    "
    ); return 1; } } for (int i = 0; i < num_thread; i++){ pthread_join(pt[i], NULL); } free(pt); free(id); return 0; }

    最終的な実行効果は次のとおりです.
    注意:コンパイル時にlibpthreadをリンクする必要があります.a: g++ xx.cc -lpthread -o xx