分享

[pthread] 同步机制(4)

 astrotycoon 2015-03-08
barrier (栅栏),就是等待 N 个线程都到达了某一阶段后,同时唤醒。N 可以由 pthread_barrier_init 设置。被唤醒的所有线程中,有一个 pthread_barrier_wait 返回值为 PTHREAD_BARRIER_SERIAL_THREAD,其它为 0。

barrier 有个 process-shared 的属性,意义不大,忽略。
--------------------------------
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>

pthread_barrier_t global_barrier;

void *mythr(void *arg)
{
    int n = (int)arg;
    printf("thr #%d, enter, time = %d\n", n, time(NULL));
    sleep(n);
    if ( pthread_barrier_wait(&global_barrier) == PTHREAD_BARRIER_SERIAL_THREAD )
            printf("thr #%d, SERIAL_THREAD, leave, time = %d\n", n, time(NULL));
    else
            printf("thr #%d, leave, time = %d\n", n, time(NULL));
    return (void *)0;
}

int main()
{
    pthread_t pid1, pid2, pid3;
    pthread_barrier_init(&global_barrier, NULL, 3);

    pthread_create(&pid1, NULL, mythr, (void *)1);
    pthread_create(&pid2, NULL, mythr, (void *)3);
    pthread_create(&pid3, NULL, mythr, (void *)5);

    pthread_join(pid1, NULL);
    pthread_join(pid2, NULL);
    pthread_join(pid3, NULL);
    return 0;
}
--------------------------------
$ ./a.out
thr #3, enter, time = 1262784886
thr #5, enter, time = 1262784886
thr #1, enter, time = 1262784886
thr #5, SERIAL_THREAD, leave, time = 1262784891
thr #1, leave, time = 1262784891
thr #3, leave, time = 1262784891
--------------------------------


barrier 的实现

barrier 的功能很简单,自己可通过 mutex, cond 手工打造一个:
-------------------------------
/* kbarrier.h */
#ifndef KCODE_KBARRIER_H
#define KCODE_KBARRIER_H

#include <pthread.h>

#define KBARRIER_SERIAL_THREAD   -1

struct kbarrier;
typedef struct kbarrier *kbarrier_t;

int kbarrier_init(kbarrier_t *b, unsigned int cnt);
int kbarrier_destoy(kbarrier_t *b);
int kbarrier_wait(kbarrier_t *b);

#endif
-------------------------------
/* kbarrier.c */
#include <stdlib.h>
#include "kbarrier.h"

struct kbarrier {
    pthread_mutex_t m;
    pthread_cond_t  cond;
    unsigned int    cnt;
};

int kbarrier_init(kbarrier_t *b, unsigned int cnt)
{
    kbarrier_t impl = (kbarrier_t) malloc(sizeof(struct kbarrier));
    pthread_mutex_init(&impl->m, NULL);
    pthread_cond_init(&impl->cond, NULL);
    impl->cnt = cnt;

    *b = impl;
    return 0;
}

int kbarrier_destoy(kbarrier_t *b)
{
    pthread_mutex_destroy(&(*b)->m);
    pthread_cond_destroy(&(*b)->cond);
    free(*b);
    return 0;
}

int kbarrier_wait(kbarrier_t *b)
{
    kbarrier_t impl = *b;
    pthread_mutex_lock(&impl->m);

    impl->cnt--;
    if ( impl->cnt == 0 )
    {
        // last thread
        pthread_mutex_unlock(&impl->m);
        pthread_cond_broadcast(&impl->cond);
        return KBARRIER_SERIAL_THREAD;
    }

    // not the last one
    pthread_cond_wait(&impl->cond, &impl->m);
    pthread_mutex_unlock(&impl->m);
    return 0;
}
-------------------------------

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多