XV6 operating system:xv6 Barriers

本文介绍如何通过条件变量(condition variables)实现线程同步,具体实现方式为编写barrier.c函数,该函数作为所有线程的起跑线,确保所有线程到达后才允许继续运行。文章详细介绍了编译及运行过程,并给出了具体的代码修改示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

此次作业是使用环境变量(condition variables)来实现barriers.c这个函数。

barrier.c的作用相当于一条起跑线,只用当所有的线程都到了起跑线的时候,系统才会允许线程继续运行(起跑),其中,先到的起跑线的进行需要等待后到起跑线的进程。

 

首先根据作业要求,下载barrier.c并放到xv6的文件夹里,然后运行它:

 

$ gcc -g -O2 -pthread barrier.c
$ ./a.out 2

系统会显示assertion Failed,到此,准备阶段完成。

 

 

然后修改barrier.c中的barrier()函数:

barrier()
{
  pthread_mutex_lock(&bstate.barrier_mutex);                                      //
对临界区进行加锁,barrier_mutex是开头定义的信号量
  bstate.nthread++;                                                                                //将到达当前barrier的线程的数量加一
  if (bstate.nthread == nthread) {                                                           //如果所有的线程都到达了当前barrier
    pthread_cond_broadcast(&bstate.barrier_cond);                             //针对barrier_cond这个环境变量广播,表示激活所有线程
    bstate.nthread = 0;
    bstate.round++;
  }
  else {
    pthread_cond_wait(&bstate.barrier_cond, &bstate.barrier_mutex);//
当还有线程没有到达barrier时,释放互斥锁,然后休眠
  }
  pthread_mutex_unlock(&bstate.barrier_mutex);                                //
释放互斥锁
}

 

再次运行程序:

 

成功

### 关于 MIT 6.828 Homework Barriers 的实现与解释 #### 障碍(Barrier)的概念 障碍是一种同步机制,用于协调多个线程的行为。当一组线程到达某个特定点时,它们会等待其他线程也达到该点后再继续执行。这种机制通常通过条件变量和互斥锁来实现。 在 `MIT6.828` 中的 Barrier 实现中,代码的核心逻辑围绕着两个主要部分展开: 1. **计数器管理**:记录进入屏障的线程数量并判断是否所有线程均已到达。 2. **条件广播/等待**:最后一个线程触发广播操作以唤醒其余线程;而未完成的线程则处于阻塞状态直至被唤醒。 以下是具体分析: --- #### 错误代码中的问题及其原因 错误代码中提到,在某些情况下即使注释掉 `pthread_cond_broadcast()` 函数调用仍然可以通过测试[^3]。然而这并不意味着程序行为完全正确。实际上,这种情况可能依赖于以下几个因素: - 测试环境下的偶然性事件序列可能导致看似正常的运行结果; - 如果恰好在线程调度过程中没有发生竞争条件或者假唤醒,则可能会掩盖潜在缺陷。 因此,尽管表面上看似乎可以省略 `broadcast` 调用,但实际上这是非常危险的做法,因为一旦遇到更复杂的并发场景就极有可能暴露出隐藏的问题。 --- #### 修改后的正确版本说明 修改版实现了更加健壮的设计模式,其中包含了必要的保护措施防止上述提及的风险情况出现: ```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 { while(bstate.round % 2 != 0){ pthread_cond_wait(&bstate.barrier_cond, &bstate.barrier_mutex); } } pthread_mutex_unlock(&bstate.barrier_mutex ); } ``` 此段修正过的源码片段里加入了循环检测环节(`while`)用来应对可能出现的操作系统级别虚假唤起现象[^4]。这样即便真的出现了意外提前苏醒状况,也能重新评估当前所处的状态从而决定下一步行动方向而不是贸然离开临界区造成数据一致性破坏等问题的发生。 --- #### 条件变量与假唤醒处理 值得注意的是,POSIX标准并未承诺绝对排除所谓的“虚假唤醒”可能性——即没有任何信号发出却依旧有线程莫名其妙地脱离了原本应该停留的位置。为此,在设计涉及长时间休眠等待的应用场合下务必采取额外预防手段比如引入显式的标志位验证机制等等方式加以规避此类隐患的存在. --- ### 总结 综上所述,对于像 Barrier 这样的多线程协作工具而言,精确控制各个阶段之间的转换关系至关重要。任何简化甚至忽略关键步骤都可能导致不可预见后果产生。所以建议严格按照既定规范编写相应功能模块的同时也要考虑到各种极端边界条件下系统的稳定性表现如何。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值