使用Pthread信号量的3线程程序无法按1,2,3循环打印的问题求助
修复Pthread线程顺序打印问题
我来帮你排查下这个Pthread程序的问题,主要有两个核心错误导致线程无法按1、2、3循环打印:
1. 信号量初始化错误
你现在把三个信号量都初始化为1了:
sem_init(&sem1, 0, 1); sem_init(&sem2, 0, 1); sem_init(&sem3, 0, 1);
这就相当于给三个线程都开了“通行许可”,它们会同时抢着执行,完全没有顺序可言。正确的逻辑应该是只有第一个线程(线程1)能先启动,所以我们要把sem1初始为1,sem2和sem3初始为0——这样线程2和线程3一开始拿不到信号量,只能等着线程1释放信号量后才能执行。
2. 信号量等待操作的位置错误
你把sem_wait放在了循环外面,比如线程1的代码:
sem_wait(&sem1); for(int i=1; i<=MAX_NUM; i++) { printf("\nF1(): %d", 1); sem_post(&sem2); }
这意味着线程1只需要等一次信号量,就能一口气把50个1全部打印完,然后才会释放50次sem2;接着线程2也会一口气打50个2,线程3打50个3,完全达不到交替打印的效果。
正确的做法是把sem_wait放到循环内部,每次打印前都要等待信号量,打印完成后再释放下一个线程的信号量——这样才能保证每次只打印一个数字,然后立刻切换到下一个线程。
修复后的完整代码
#include <pthread.h> #include <stdio.h> #include <semaphore.h> #include <unistd.h> #define MAX_NUM 50 sem_t sem1, sem2, sem3; void *f1(void*) { for(int i=1; i<=MAX_NUM; i++) { sem_wait(&sem1); // 每次打印前等待信号量,确保拿到许可 printf("F1(): %d\n", 1); sem_post(&sem2); // 释放线程2的信号量,让它可以执行 } return NULL; // 线程函数需要返回值,避免编译警告 } void* f2(void*) { for(int i=1; i<=MAX_NUM; i++) { sem_wait(&sem2); printf("F2(): %d\n", 2); sem_post(&sem3); } return NULL; } void* f3(void*) { for(int i=1; i<=MAX_NUM; i++) { sem_wait(&sem3); printf("F3(): %d\n", 3); sem_post(&sem1); // 释放线程1的信号量,形成循环 } return NULL; } int main() { pthread_t p1, p2, p3; // 正确初始化信号量:只有sem1初始为1,其余为0 sem_init(&sem1, 0, 1); sem_init(&sem2, 0, 0); sem_init(&sem3, 0, 0); pthread_create(&p1, NULL, f1, NULL); pthread_create(&p2, NULL, f2, NULL); pthread_create(&p3, NULL, f3, NULL); pthread_join(p1, NULL); pthread_join(p2, NULL); pthread_join(p3, NULL); // 销毁信号量,避免资源泄漏 sem_destroy(&sem1); sem_destroy(&sem2); sem_destroy(&sem3); return 0; }
修复后的逻辑说明
- 程序启动时,只有
sem1有1个许可,线程1可以立刻进入循环打印1,然后释放sem2; - 线程2拿到
sem2的许可后打印2,接着释放sem3; - 线程3拿到
sem3的许可后打印3,最后释放sem1,回到线程1开始下一轮循环; - 每个循环迭代都严格遵循“等待→打印→释放下一个”的流程,完美保证1、2、3的循环顺序;
- 另外补充了线程函数的返回值和信号量销毁操作,避免编译警告和资源泄漏。
内容的提问来源于stack exchange,提问作者Nripendra
相关产品推荐
相关产品推荐

