Barriers 实验报告
实验内容
通过使用pthread library提供的条件变量来实现一个Barrier。Barrier是应用中的一个节点,所有线程到达这一结点后必须停止等待,直到所有线程都已经到达这一节点后,再继续执行。
struct barrier { pthread_mutex_t barrier_mutex; pthread_cond_t barrier_cond; int nthread; // Number of threads that have reached this round of the barrier int round; // Barrier round } bstate;
实验代码及思路
主要代码
static void
barrier()
{
pthread_mutex_lock(&bstate.barrier_mutex); // 临界资源
bstate.nthread++; // 获得锁,进入次round的线程多一
if(bstate.nthread < nthread){ // 本轮operation还未结束禁止进入下一轮
// printf("11\n");
pthread_cond_wait(&bstate.barrier_cond, &bstate.barrier_mutex);
}
else{
// printf("22\n");
bstate.nthread = 0;
bstate.round+=1;
pthread_cond_broadcast(&bstate.barrier_cond);
}
pthread_mutex_unlock(&bstate.barrier_mutex); // 殊途同归
}
思路:
根据要求需要等待所有线程达到barrier后再继续下一轮(round).
bstate.nthread
就是用于记录本轮已经完成操作开始等待的线程
注意到
for (i = 0; i < 20000; i++) {
int t = bstate.round;
assert (i == t);
barrier();
usleep(random() % 100);
}
assert (i == t);
>> 目标
也就是说有20000轮,每轮要求所有线程都完成本轮操作才可以进行下一轮(抽象出的模型
pthread_mutex_lock 上锁,保护临界资源 round
pthread_cond_wait 挂起,等待其它未完成操作的线程(在本轮)
pthread_cond_broadcast 当本轮最后一个线程完成了操作,唤醒其他挂起的线程
pthread_mutex_unlock 注意解锁
中间注意轮数的增加,等待线程数的归零
Warning
-
pthread_cond_wait
被唤醒后会尝试获得锁➡️如果没锁就会阻塞直到获得锁,➡️如果后续没有释放锁的话,就bug了
所以我把unlock放在了外面,必经的出口
-
用循环还是条件
循环的作用是再判断,即条件是动态的,资源的访问有限要实时判断
条件影响操作的执行
条件则意味着无需再次判断,或者不可再次判断
此时先执行操作然后再wait