您的位置:首页 > 其它

多线程之如何构造自己的barrier函数?(七)

2018-02-10 21:18 288 查看

1. 题目

What synchronization primitives would you need to implement a barrier? Provide an implementation of the pthread_barrier_wait function.

int pthread_barrier_wait(pthread_barrier_t *barrier);
Returns: 0 or PTHREAD_BARRIER_SERIAL_THREAD if OK, error number on failure


2. 审题

  基于上一篇的描述,
pthread_barrier_wait
的特性感觉和
variable condition
很像啊,所以完全可以尝试用
variabl condition
来试试水:

pthread_barrier_init
指定了
count


pthread_barrier_wait
的调用会使内部计数值加1,如果计数值没达到
count
,则当前线程休眠。否则,唤醒全部在该函数调用处休眠的线程。

pthread_barrier_wait
返回后继续执行后续的代码段,并在任意线程中返回
PTHREAD_BARRIER_SERIAL_THREAD


3. 程序展示

3.1 设计的API展示

typedef struct {
pthread_mutex_t barrier_mutex;
unsigned int count;
unsigned int max_count;
pthread_cond_t barrier_cond;
} pthread_barrier;

int pthread_barrier_init_1(pthread_barrier *restrict barrier, unsigned int count)
{
if ( pthread_mutex_init(&barrier->barrier_mutex,NULL) != 0)
return -1;
if ( pthread_cond_init(&barrier->barrier_cond,NULL) != 0)
return -1;
barrier->max_count=count;
barrier->count=0;
return 0;
}

int pthread_barrier_wait_1(pthread_barrier *barrier)
{
pthread_mutex_lock(&barrier->barrier_mutex);
barrier->count++;
if(barrier->count < barrier->max_count)
{
pthread_cond_wait(&barrier->barrier_cond,&barrier->barrier_mutex);
pthread_mutex_unlock(&barrier->barrier_mutex);
}
else
{
pthread_cond_broadcast(&barrier->barrier_cond);
pthread_mutex_unlock(&barrier->barrier_mutex);
return PTHREAD_BARRIER_SERIAL_THREAD;
}
return 0;
}


3.2 应用该API

  其中用到了
variable-condition
,现在我们用上面自己构造
pthread_barrier
的替换掉其中使用的
variable condition
看看运行效果如何。

[root@localhost ~]# diff -Naur 11_4.c 11_8.c
--- 11_4.c      2018-02-09 17:48:17.463201599 +0800
+++ 11_8.c      2018-02-10 21:15:02.094194080 +0800
@@ -12,10 +12,47 @@
struct foo * f_next;
};

+typedef struct {
+       pthread_mutex_t barrier_mutex;
+       unsigned int count;
+       unsigned int max_count;
+       pthread_cond_t barrier_cond;
+} pthread_barrier;
+
struct foo *fh[NHASH];
pthread_mutex_t hashlock = PTHREAD_MUTEX_INITIALIZER;
-pthread_mutex_t hashr_mutex = PTHREAD_MUTEX_INITIALIZER;
-pthread_cond_t hashr_cond = PTHREAD_COND_INITIALIZER;
+pthread_barrier barrier;
+
+
+
+int pthread_barrier_init_1(pthread_barrier *restrict barrier, unsigned int count)
+{
+        if ( pthread_mutex_init(&barrier->barrier_mutex,NULL) != 0)
+               return -1;
+        if ( pthread_cond_init(&barrier->barrier_cond,NULL) != 0)
+               return -1;
+        barrier->max_count=count;
+        barrier->count=0;
+        return 0;
+}
+
+int pthread_barrier_wait_1(pthread_barrier *barrier)
+{
+        pthread_mutex_lock(&barrier->barrier_mutex);
+               barrier->count++;
+        if(barrier->count < barrier->max_count)
+        {
+               pthread_cond_wait(&barrier->barrier_cond,&barrier->barrier_mutex);
+               pthread_mutex_unlock(&barrier->barrier_mutex);
+        }
+        else
+        {
+               pthread_cond_broadcast(&barrier->barrier_cond);
+               pthread_mutex_unlock(&barrier->barrier_mutex);
+               return PTHREAD_BARRIER_SERIAL_THREAD;
+        }
+        return 0;
+}

void  foo_printf(struct foo * a)
{
@@ -68,7 +105,7 @@
}
else
{
-                            fp1=fh[HASH(id)];
+                                fp1=fh[HASH(id)];
while (fp1->f_next != fp)
fp1 = fp1->f_next;
fp1->f_next = fp->f_next;
@@ -93,13 +130,11 @@
}
else
{
-                pthread_mutex_lock(&hashr_mutex);
-                pthread_cond_wait(&hashr_cond,&hashr_mutex);
+                pthread_barrier_wait_1(&barrier);
if(foo_rele((int)arg) != 0)
{
errx(1,"error in release the foo of the id : %d",(int)arg);
}
-                pthread_mutex_unlock(&hashr_mutex);
return((void *)0);
}
}
@@ -124,6 +159,10 @@
int done[3]={4,4,4};
pthread_t tid;
char i=0;
+       if(pthread_barrier_init_1(&barrier,NHASH+1) != 0)
+       {
+               errx(1,"error in initing barrier\n");
+       }
for( num=0;num<NHASH;num++)
{
err = pthread_create(&tid,
4000
NULL, thr_fn,(void *)(num*NHASH));
@@ -140,10 +179,8 @@
done[i++]=num;
if(i>=NHASH)
{
-                                                pthread_mutex_lock(&hashr_mutex);
-                                                pthread_cond_broadcast(&hashr_cond);
-                                                pthread_mutex_unlock(&hashr_mutex);
-                                                exit(0);
+                                               pthread_barrier_wait_1(&barrier);
+                                               exit(0);
}
}
}


四:结果分析

[root@localhost ~]# ./11_8
thread 139879873591040, foo_id:3
thread 139879890442048, foo_id:3
thread 139879881983744, foo_id:0
thread 139879890442048, foo_id:0
thread 139879865198336, foo_id:6
thread 139879890442048, foo_id:6


  很好的完成了任务,其实这也是理所当然的,笔者用
variable condition
实现的
barrier
,所以换汤不换药,自然和上一次实验结果相同。就不过多赘述,如果您对以上内容有所质疑,请及时指正笔者!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: