You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多线程环境下信号量sem_wait与sem_post的正确插入位置咨询

多线程环境下信号量sem_wait与sem_post的正确插入位置咨询

Hey there, let's break this down step by step so you understand exactly what's going on here.

First, let's clean up the code snippet you provided for clarity:

#include <semaphore.h>  // 补全信号量所需的头文件
sem_t s;
sem_init(&s, 0, 1);  // 初始化二进制信号量(值为1,用作互斥锁)
......
8. 
9. while (bucket_size > 0) {
10. 
11. 
12. printf("I am filling the bucket with 1 cup and the bucket is %i.\n", bucket_size);
13. 
14. 
15. bucket_size--;
16. 
17. 
18. }
19. ......

核心问题拆解

我们要保护的是临界区——也就是访问共享变量bucket_size和打印其值的代码段。如果多线程无同步地运行这段代码,会出现竞态条件:比如多个线程同时修改bucket_size导致数值错误,或者打印时变量正在被修改,输出混乱结果。同时我们还要保证多个线程都能参与填充,不能让单个线程垄断整个过程。

信号量的作用要明确:

  • sem_wait(&s):相当于"加锁"操作,会把信号量的值减1。如果值为0,线程会等待直到其他线程释放信号量。
  • sem_post(&s):相当于"解锁"操作,会把信号量的值加1,让等待的线程可以继续执行。

正确插入位置分析

我们需要用信号量包裹临界区(第12行的打印和第15行的变量修改),同时保证每个线程都有机会参与填充,正确的位置是:

  • sem_wait(&s) 放在第10行:进入while循环后、访问bucket_size之前加锁,确保同一时间只有一个线程能进入临界区。
  • sem_post(&s) 放在第17行:修改完bucket_size之后、退出当前循环迭代之前解锁,让其他线程可以获取锁执行填充操作。

为什么其他选项不行

快速排除错误选项帮你加深理解:

  • 把sem_wait放在第8行(while循环之前):会导致单个线程获取锁后,一直把bucket_size减到0才释放锁,其他线程完全没机会参与,违背了"越多填充者越好"的要求。
  • 把sem_post放在第19行(循环之后):和上面的问题一样,线程会垄断整个填充过程,其他线程无法介入。
  • 把操作放在临界区内部(比如第14、16行):要么是在访问共享变量之后加锁(竞态条件已经发生,锁毫无意义),要么是在完成临界区操作之前解锁(仍然会出现竞态问题)。

最终结论

  • sem_wait(&s) → 第10行
  • sem_post(&s) → 第17行

这个配置既保证了临界区的互斥访问,避免了竞态条件,又能让多个线程轮流参与填充,完全符合问题要求。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 11:53:01