pthread 屏障

屏障 (Barrier) 允許每個線程都處於等待狀態,直到所有的合作線程都達到某一執行點,然後從該點繼續執行。pthread_join(tid) 就是一種最簡單的「屏障」行爲,允許當前線程等待 tid 線程的完成。

Barrier 的範圍更廣,它允許任意數量的線程處於等待狀態,直到所有線程完成工作,而線程不需要退出,所有線程到達 Barrier 後可以繼續執行。

API

相關數據結構:

  • pthread_barrier_t :屏障的數據結構;
  • pthread_barrierattr_t:屏障屬性的數據結構。

init and destroy

函數原型:

int pthread_barrier_destroy(pthread_barrier_t *barrier);
int pthread_barrier_init(pthread_barrier_t *restrict barrier,
                         const pthread_barrierattr_t *restrict attr, unsigned count);

作用:初始化/銷燬 barrier .

count 參數表示在允許所有線程繼續執行前,必須達到 barrier 的線程的數量。

wait

函數原型:

int pthread_barrier_wait(pthread_barrier_t *barrier);

返回值:若成功,返回 0 或者 PTHREAD_BARRIER_SERIAL_THREAD(-1), 其中有且只有一個線程會返回 PTHREAD_BARRIER_SERIAL_THREAD ,其餘返回 0 ,返回 PTHREAD_BARRIER_SERIAL_THREAD 的線程可以作爲主線程,處理、合併其他線程的工作;失敗則返回錯誤碼。

作用:使得 barrier 的計數加一,如果不滿足條件(即計數結果未達到初始化時設定的 count ),線程進入 sleep 休眠狀態。如果當前線程調用 wait 後,滿足了 barrier 條件,那麼在該 barrier 上等待的所有線程都將被喚醒。

Example

多線程排序,在主線程合併。

#include <pthread.h>
#include <stdio.h>
#include <sys/time.h>
#include <string.h>
#include <limits.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include <stdlib.h>

#define NTHR 8
#define N 8000000L
#define TNUM (N / NTHR)

int nums[N] = {0};
int snums[N] = {0};
pthread_barrier_t barrier;

int x = 0;
int cmp(const void *a, const void *b)
{
    int x = *(int *)a;
    int y = *(int *)b;
    return x - y;
}
void merge()
{
    uint64_t idx[NTHR];
    uint64_t i, minidx, sidx;
    int num;
    for (i = 0; i < NTHR; i++) idx[i] = i * TNUM;
    for (sidx = 0; sidx < N; sidx++)
    {
        num = 0x7fffffff;
        for (i = 0; i < NTHR; i++)
        {
            if ((idx[i] < (i + 1) * TNUM) && (nums[idx[i]] < num))
            {
                num = nums[idx[i]];
                minidx = i;
            }
        }
        snums[sidx] = nums[idx[minidx]];
        idx[minidx]++;
    }
}

void *worker(void *args)
{
    uint64_t idx = (u_int64_t)args;
    qsort(&nums[idx], TNUM, sizeof(int), cmp);
    pthread_barrier_wait(&barrier);
    return NULL;
}

int main()
{
    int i = 0, ret = 0;
    pthread_t tid;

    // init numbers array
    srandom(time(NULL));
    for (i = 0; i < N; i++)
        nums[i] = random() % 100;

    // init barrier
    pthread_barrier_init(&barrier, NULL, NTHR + 1);

    // create NTHR threads
    for (i = 0; i < NTHR; i++)
    {
        ret = pthread_create(&tid, NULL, worker, (void *)(i * TNUM));
        if (ret != 0)
        {
            puts(strerror(ret));
            exit(ret);
        }
    }
    // wait here
    pthread_barrier_wait(&barrier);
    merge();
    pthread_barrier_destroy(&barrier);

    // check whether if increase order
    for (i = 1; i < N; i++)
        assert(snums[i] >= snums[i - 1]);
    // print sorted result
    // for (i = 0; i < N; i++)
    //     printf("%d%c", snums[i], i == N - 1 ? '\n' : ' ');
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章