当前位置: 代码迷 >> 综合 >> unix 屏障的理解(barrier)
  详细解决方案

unix 屏障的理解(barrier)

热度:80   发布时间:2023-12-27 14:54:39.0
11.6.8 屏障场景:barrier就像公园的管理员一样, 只有来准备参观的人数达到一定的数量(比如30),管理员才放行到园区游览。1.“公园”指进程的共享数据2.“一定的人数”指pthread_barrier_init函数传入的屏蔽数count3.“达到”指调用pthread_barrier_wait函数的线程个数4.“放行”:“一定的人数”达到后,各线程才可继续执行。5.“游览”:”放行“后,各个线程的独立运行。6.”准备参观的人“:"游客"加入了排队队列,等待放行。7.进公园参观的人何时出来,"管理员"是不知道的。// "每个线程都独立运行"(1)概述1.屏障是用户协调多个线程并行工作的同步机制。2.屏障允许每个线程等待,直到所有的合作线程都达到某一点,然后从改点继续执行。3.pthread_join函数就是屏障的一种特例,允许一个线程等待,直到另一个线程退出。(2)屏障对象	1.屏障对象允许任意数量的线程等待,直到所有的线程完成处理工作,而线程不需要退出。2.所有线程达到屏障后可以接着工作。(3)屏障对象的创建、销毁int pthread_barrier_init(pthread_barrier_t *barrier, const barrierattr_t *attr, unsigned int count);attr: 屏障属性count: 需要屏蔽的线程数int pthread_barrier_destroy(pthread_barrier_t *barrier)int pthread_barrier_wait(pthread_barrier_t *barrier)// 该函数表明当期线程已经完成工作,准备等其他所有线程赶上来1.调用该函数的线程在屏蔽计数count未满足条件时,会进入休眠状态。2.如果该线程是最后一个调用pthread_barrier_wait的线程,就满足了屏蔽计数,所有的线程都被唤醒。3.对于任意一个线程,pthread_barrier_wait函数返回了PTHREAD_BARRIER_SERIAL_THREAD。剩下的线程看到的返回值是0.这使得一个线程可以作为主线程,他可以工作在其他所有线程已完成的工作结果上。(4)屏蔽的复用一旦达到屏蔽计数器数值,而且线程处于非阻塞状态,屏蔽就可以被重用。但是除非在调用了pthread_barrier_destory函数之后又调用了pthread_barrier_init函数对计数用另外的数进行初始化,否则屏蔽计数器不会改变。(5)注意虽然屏蔽对象数count已经达到要求,如果再次调用pthread_barrier_wait仍然会使调用线程阻塞。

测试代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/wait.h>
#include <sys/acct.h>
#include <errno.h>
#include <sys/times.h>
#include <pthread.h>
#include <signal.h>/*
场景:barrier就像公园的管理员一样, 只有来准备参观的人数达到一定的数量(比如30),管理员才放行到园区游览。1.“公园”指进程的共享数据2.“一定的人数”指pthread_barrier_init函数传入的屏蔽数count3.“达到”指调用pthread_barrier_wait函数的线程个数4.“放行”:“一定的人数”达到后,各线程才可继续执行。5.“游览”:”放行“后,各个线程的独立运行。6.”准备参观的人“:运行线程做好的初始化。7.进公园参观的人何时出来,"管理员"是不知道的。// "每个线程都独立运行"
*/
/*
测试结果:new queue NNNNNNNNNNNNNNNNNNNNNNNNNNNI(tid=140132835755776) + 1I(tid=140132827363072) + 1I(tid=140132818970368) + 1I(tid=140132810577664) + 1I(tid=140132802184960) + 1old queue ==========================>see younew queue NNNNNNNNNNNNNNNNNNNNNNNNNNNI(tid=140132810577664) + 1I(tid=140132818970368) + 1I(tid=140132802184960) + 1I(tid=140132827363072) + 1I(tid=140132835755776) + 1old queue ==========================>see younew queue NNNNNNNNNNNNNNNNNNNNNNNNNNNI(tid=140132827363072) + 1I(tid=140132818970368) + 1I(tid=140132802184960) + 1I(tid=140132810577664) + 1I(tid=140132835755776) + 1old queue ==========================>see younew queue NNNNNNNNNNNNNNNNNNNNNNNNNNNI(tid=140132802184960) + 1I(tid=140132827363072) + 1I(tid=140132818970368) + 1I(tid=140132810577664) + 1
*/
static pthread_t g_tid;
static pthread_barrier_t barrier;
static pthread_t tid;
#define FIXED_RELEASE_NUM 6		// 固定的放行人数+1, 管理员等着5个人,相当于有6个人要等待void *new_tourist(void *arg)
{printf("I(tid=%lu) + 1\n", pthread_self());	pthread_barrier_wait(&barrier); 				// 参观者加入了排队队列,等待放行		//printf("I(tid=%lu) start\n", pthread_self());	// 参观者被放行了,开始参观//usleep(100);//printf("I(tid=%lu) end\n", pthread_self());		// 参观结束return (void *)0;
}// 模拟一个新的参观者
void line_up(int sig)
{pthread_create(&tid, NULL, new_tourist, NULL);	pthread_detach(tid);alarm(1);	// 每一秒来一个参观者
}int main(int argc, char **argv)
{struct sigaction act;act.sa_handler = line_up;sigaction(SIGALRM, &act, NULL);	alarm(1);	// 每一秒来一个参观者new_queue:	printf("new queue NNNNNNNNNNNNNNNNNNNNNNNNNNN\n");// 管理员规定排队达到5个人才放行进园pthread_barrier_init(&barrier, NULL, FIXED_RELEASE_NUM);pthread_barrier_wait(&barrier); 				// 参观者加入了排队队列,等待放行		// 已经放行, 第2,3,4...n次排队printf("old queue ==========================>see you\n");pthread_barrier_destroy(&barrier);goto new_queue;pause();return 0;
}

 

  相关解决方案