多线程环境下信号量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
相关产品推荐
相关产品推荐

