Pthread 開發-入門

Pthread 開發-入門

在內存共享式的多處理器架構中,線程可用用於實現並行機制(parallelism)。然而由於歷史原因,硬件供應商們的對線程的實現並不相同,使得開發者不得不考慮代碼移植問題。對於UNIX系統,存在一套基於 IEEE POSIX 1003.1c 標準的標準 C 語言線程編程接口,這就是 Pthread。
Pthread 線程庫主要分爲三個主要部分:線程管理,互斥量,條件變量。共有約100個 API,它們可以分爲以下四種範疇:
1. 線程管理:負責線程的創建,分發,等待等,以及設置/獲取線程屬性
2. 互斥量:使用 mutex 進行線程同步,包括mutex的創建,銷燬,加鎖和解鎖,以及 mutex 的屬性設置
3. 條件變量 :基於開發者指定的條件, 處理使用 mutex進行通信,包括condition variable的創建,銷燬, 等待和通知,以及 屬性設置
4. 同步:用於管理讀寫鎖和屏障( barriers)

從函數的命名可以更清楚地瞭解這些分類:

Routine Prefix Functional Group
pthread_ Threads themselves and miscellaneous subroutines
pthread_attr_ Thread attributes objects
pthread_mutex_ Mutexes
pthread_mutexattr_ Mutex attributes objects.
pthread_cond_ Condition variables
pthread_condattr_ Condition attributes objects
pthread_key_ Thread-specific data keys
pthread_rwlock_ Read/write locks
pthread_barrier_ Synchronization barriers

具體後面將會分別介紹。以下是一個Pthread 基本使用的例子

#include <unistd.h>
#include <errno.h>
#include <pthread.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static const int ntimes = 10;

void* threadfunc(void* arg)
{
    pthread_t tid = pthread_self();

//  int ret;
//      if(0 != (ret=pthread_detach(tid))) {
//          fprintf(stderr, "pthread_detach:%s\n", strerror(ret));
//      exit(EXIT_FAILURE);
//      }

    printf("Thread B %#lx starting\n", (size_t)tid);

    int i;
    for(i=0; i<ntimes; ++i) {
        printf("[B-%d]", i);
        fflush(stdout);
        if(3 == i) {
            pthread_exit("Thread B breaked");   
        }
    }

    return "Thread B findshed!";
}

int main()
{
        pthread_t tid; //thread B TID
        int ret;
        if(0 != (ret=pthread_create(&tid, NULL, threadfunc, NULL))) {
            fprintf(stderr, "pthread_create:%s\n", strerror(ret));
        exit(EXIT_FAILURE);
        }

    printf("Thread A %#lx starting\n", (size_t)pthread_self());

    int i;
    for(i=0; i<ntimes; ++i) {
        printf("[A-%d]", i);
        fflush(stdout);
    }
    printf("\n");

    // 不可與 pthread_detach 同時使用,且 pthread_join 一般用在線程處理函數外
    void *value_ptr;
        if(0 != (ret=pthread_join(tid, &value_ptr))) {
            fprintf(stderr, "pthread_join:%s\n", strerror(ret));
        exit(EXIT_FAILURE);
        }
    printf("Receive msg: %s\n", (char*)value_ptr);

    exit(EXIT_SUCCESS);
}

編譯運行:

gcc -o proc demo1.c -lpthread

這裏寫圖片描述

上例中程序首先調用pthread_create函數創建線程,併爲新線程設置回調函數 threadfunc,新線程創建完畢後,主線程繼續執行,新線程並行執行,並各自輸出相應的信息,新線程調用 pthread_exit 退出,主線程調用pthread_join函數等待新線程結束。要注意的是:pthread 函數出錯時並不會更改全局變量 errno 對它進行錯誤處理時要注意。
這裏對比一下Pthread 和系統進程管理API:

Process Thread
fork pthread_create
getpid pthread_self
waitpid pthread_join
kill pthread_exit

簡要介紹程序使用到的 Pthread 函數:

int pthread_create(pthread_t *restrict thread, const pthread_attr_t *restrict attr, void *(*start_routine)(void *), void *restrict arg);

用於創建一個新線程,參數thread是新線程的 ID,attr用於指定線程的屬性,一般可以用 NULL,表示使用默認屬性。start_routine和 arg 是線程回調函數和參數。

    pthread_t pthread_self(void);

返回調用線程的線程 ID

 int  pthread_join(pthread_t thread, void **value_ptr);

等待線程退出。參數value_ptr用於存儲 pthread_exit 傳遞的信息,該函數用在線程回調函數外,而另一個函數 pthread_detach一般用在回調函數中。

int  pthread_detach(pthread_t thread);

分離線程一般用在回調函數中,在線程執行結束後,線程分配內存即被回收,避免產生殭屍線程

 void  pthread_exit(void *value_ptr);

終止線程,並將 value_ptr 傳遞給該線程的pthread_join函數。注意除main函數以外的線程的回調函數在返回時會隱式調用該函數

推薦一個 Pthread 學習網站:https://computing.llnl.gov/tutorials/pthreads/#MutexLocking
並行編程: https://computing.llnl.gov/tutorials/parallel_comp/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章