使用Semaphore实现线程同步的打印序列异常问题求助
修复信号量同步逻辑实现线程循环打印"1234 1234..."
你的代码问题在于信号量的同步逻辑没有严格控制打印顺序:p1在每一轮循环开始时未等待信号量就直接打印"1",同时p2打印完"4"后没有触发下一轮的p1执行,最终导致输出顺序错乱。
以下是两种修复后的实现方案:
方案一:用四个信号量精确控制每一步
#include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <semaphore.h> sem_t s_print1, s_print2, s_print3, s_print4; void *p1(void *arg) { while (1) { sem_wait(&s_print1); // 等待打印1的权限 printf("1"); sem_post(&s_print2); // 通知p2可以打印2 sem_wait(&s_print3); // 等待打印3的权限 printf("3"); sem_post(&s_print4); // 通知p2可以打印4 } return NULL; } void *p2(void *arg) { while (1) { sem_wait(&s_print2); // 等待打印2的权限 printf("2"); sem_post(&s_print3); // 通知p1可以打印3 sem_wait(&s_print4); // 等待打印4的权限 printf("4 "); sem_post(&s_print1); // 触发p1开始下一轮循环 } return NULL; } int main() { // 初始化:让p1先打印1,其余步骤初始无权限 sem_init(&s_print1, 0, 1); sem_init(&s_print2, 0, 0); sem_init(&s_print3, 0, 0); sem_init(&s_print4, 0, 0); pthread_t t1, t2; pthread_create(&t1, NULL, p1, NULL); pthread_create(&t2, NULL, p2, NULL); pthread_join(t1, NULL); pthread_join(t2, NULL); sem_destroy(&s_print1); sem_destroy(&s_print2); sem_destroy(&s_print3); sem_destroy(&s_print4); return 0; }
修复关键点:
- 每个打印步骤对应独立信号量,只有收到前一步的通知(
sem_post)才能执行当前打印,严格保证1→2→3→4的顺序。 - p2打印完"4 "后,通过
sem_post(&s_print1)触发p1开始下一轮,形成完整循环。 - 初始信号量
s_print1设为1,确保程序启动后p1先执行。
方案二:用两个信号量简化实现
#include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <semaphore.h> sem_t sem_p1, sem_p2; void *p1(void *arg) { while (1) { sem_wait(&sem_p1); printf("1"); sem_post(&sem_p2); sem_wait(&sem_p1); printf("3"); sem_post(&sem_p2); } return NULL; } void *p2(void *arg) { while (1) { sem_wait(&sem_p2); printf("2"); sem_post(&sem_p1); sem_wait(&sem_p2); printf("4 "); sem_post(&sem_p1); } return NULL; } int main() { sem_init(&sem_p1, 0, 1); // 初始允许p1执行 sem_init(&sem_p2, 0, 0); pthread_t t1, t2; pthread_create(&t1, NULL, p1, NULL); pthread_create(&t2, NULL, p2, NULL); pthread_join(t1, NULL); pthread_join(t2, NULL); sem_destroy(&sem_p1); sem_destroy(&sem_p2); return 0; }
简化逻辑说明:
sem_p1控制p1的打印权限,sem_p2控制p2的打印权限。- 交替释放信号量:p1打印后给p2权限,p2打印后给p1权限,同样能严格保证1→2→3→4的顺序循环。
内容的提问来源于stack exchange,提问作者Badreddine
相关产品推荐
相关产品推荐

