任务:修改代码以实现对于每一个循环,让每一个线程都暂时阻塞直到所有线程都调用了barier函数
实际上就是实现一个屏障,当线程运行到屏障之前,会被暂时挂起,直到所有线程都到达屏障之后才会继续运行
而在原始的代码中,由于 barriers 函数中没有进行处理,sleep 较短时间的线程必定会比另一线程更早离开 barrier,进入下一个循环,从而发生错误。
在 barrier 函数的编写过程中需要维护两个变量,bstate.nthread 和 bstate.round。
- bstate.thread 指示已到达屏障的线程的数量,用于判断是否应阻塞线程
- bstate.round 指示当前的循环的数目,用于测试是否有线程提前离开了屏障。
进入 barrier 后,在加锁的基础上,首先将bstate.nthread 加 1,代表到达屏障的线程有多了一个;接着比较bstate.nthread 和 nthread 判断是否所有线程都已经到达屏障,如果没有全部到达,阻塞当先线程,加入等待队列,如果全部到达,bstate.round加 1,bstate.nthread置为 0 供下一轮循环使用,唤醒等待队列中的所有线程。
最终的barrier.c函数如下:
static void
barrier()
{
pthread_mutex_lock(&bstate.barrier_mutex);
bstate.nthread++;
if(bstate.nthread == nthread)
{
bstate.round++;
bstate.nthread = 0;
pthread_cond_broadcast(&bstate.barrier_cond);
}
else
{
pthread_cond_wait(&bstate.barrier_cond, &bstate.barrier_mutex);
}
pthread_mutex_unlock(&bstate.barrier_mutex);
}
最终测试结果如下:
❯ ./a.out 4
OK; passed
标签:Thread,barrier,locking,nthread,屏障,线程,mutex,MIT,bstate
From: https://www.cnblogs.com/tea-in-the-snow/p/16881610.html