先以一张简图说明 barrier
(From Quora)
Barrier 是一个 简易的程序 限制 多进程/多线程 之间冲突, 防止出现 锁死情况 (dead_lock) 以及进程 同时运行冲突
barrier 在线程 和 进程 之中有同样的运行 原理
第一步, 为了达到 多线程/进程 我们需要一个 通用变量
这种 通用变量 以很多形式存在与 程序里面: Gobal 变量 , mmap() 一个虚拟量, 或者是一个打开的 输出文件
先以 sem_h 的方法为例子 去讲解 barrier,
typedef struct barrier {
sem_t barrier;
sem_t mutex;
int count;
int seen;
} barrier;
#include
semaphore 意思是一种信号 传递程序之间是否运行 运行
barrier*
make_barrier(int nn)
{
int rv;
barrier* bb = mmap(0, sizeof(barrier), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if ((long) bb == -1) {
perror("mmap(barrier)");
abort();
}
rv = sem_init(&(bb->barrier), 1, 0);
if (rv == -1) {
perror("sem_init(barrier)");
abort();
}
sem_init(&(bb->mutex), 1, 1);
if (rv == -1) {
perror("sem_init(mutex)");
abort();
}
bb->count = nn;
bb->seen = 0;
return bb;
}
sem_init
int sem_init(sem_t *sem, int pshared, unsigned int value);
*sem sem产量 的地址
pshared 是否允许共享 值为0意思 可以共享在 线程之间 其余的值则是允许共享在不同进程中间
value 初始一个初始数值
Return 运行成功,输出0
void
barrier_wait(barrier* bb)
{
int rv;
rv = sem_wait(&(bb->mutex));
if (rv == -1) {
perror("sem_wait(mutex)");
abort();
}
bb->seen += 1;
int seen = bb->seen;
rv = sem_post(&(bb->mutex));
if (rv == -1) {
perror("sem_post(mutex)");
abort();
}
if (seen >= bb->count) {
for (int ii = 0; ii < bb->count; ++ii) {
rv = sem_post(&(bb->barrier));
if (rv == -1) {
perror("sem_post(barrier1)");
abort();
}
}
}
rv = sem_wait(&(bb->barrier));
if (rv == -1) {
perror("sem_wait(barrier)");
abort();
}
}
这个barrier 设计是 检查是否所有进程运行完善
count 等于所有进程个数
seen 等于所有完成进程个数
如果 不相等 barrier 会阻止程序运行 反之亦然
int sem_wait(sem_t *sem);
如果 sem 的值大于 0, 这个方程 锁住 sem
int sem_post(sem_t *sem);
如果 sem 等于 0, 解锁.
===============================================
首先 在运行 fork()划分多进程之前
make_barrier()
当进程要一起更改 一个 参数的之前
放置
barrier_wait()
会检测是否所用进程 都完成之前的工作 导致不会出现 同时性 运动.
// 最后别忘了 free 哦
相同的原理
不过不适用 sem 与之代替的是 直接用 pthread, 更有效率
#include
#include
#include
#include
#include
#include "barrier.h"
// create a barrier, initialize all elements in the barrier, two threads,
// count shuold equal to the size of array, and seen is the waiting number
// of threads.
barrier*
make_barrier(int nn)
{
int rv;
barrier* bb = malloc(sizeof(barrier));
if ((long) bb == -1) {
perror("malloc(barrier)");
abort();
}
rv = pthread_mutex_init(&(bb->mutex), 0);
if (rv != 0) {
perror("pthread_mutex_init(mutex)");
abort();
}
rv = pthread_cond_init(&(bb->condv), 0);
if (rv != 0) {
perror("pthread_cond_init(condv)");
abort();
}
bb->count = nn;
bb->seen = 0;
return bb;
}
// put the function before each local array save into output file. it can
// check all thread completion, then, the lock would be unlock satues.
void
barrier_wait(barrier* bb)
{
pthread_mutex_lock(&bb->mutex);
bb->seen++;
if(bb->count != bb->seen) {
pthread_cond_wait(&bb->condv, &bb->mutex);
} else {
pthread_cond_broadcast(&bb->condv);
}
pthread_mutex_unlock(&bb->mutex);
}
void
free_barrier(barrier* bb)
{
free(bb);
}
#原创
#如有问题询问作者
#点赞收藏 哈哈哈