linux 信号量线程同步的问题


下面的代码中主线程创建一个新线程用来统计输入的字符串中字符的个数。而且它偶尔会将来自键盘的输入用事先准备号的文本自动替换掉~

代码:

   
  #include <stdio.h>
  
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>

//线程函数
void *thread_function(void *arg);

sem_t bin_sem;//信号量对象

#define WORK_SIZE 1024

char work_area[WORK_SIZE];//工作区

int main()
{
int res;
pthread_t a_thread;
void *thread_result;

res = sem_init(&bin_sem,0,0);//初始化信号量对象

if(res)//初始化信号量失败
{
perror("Semaphore initialization failed\n");
exit(EXIT_FAILURE);
}

//创建新线程
res = pthread_create(&a_thread,NULL,thread_function,NULL);
if(res)
{
perror("Thread creation failed\n");
exit(EXIT_FAILURE);
}

printf("Input some text.Enter 'end' to finish\n");

while(strncmp("end",work_area,3) != 0)
{//输入没有结束
if(strncmp(work_area,"FAST",4) == 0)
{
sem_post(&bin_sem);
strcpy(work_area,"Wheeee...");
}
else
{
fgets(work_area,WORK_SIZE,stdin);
sem_post(&bin_sem);//给信号量值加一
}
sem_post(&bin_sem);//给信号量值加一
}

printf("waiting for thread to finish\n");

//等待子线程结束,收集子线程信息
res = pthread_join(a_thread,&thread_result);
if(res)
{
perror("Thread join failed\n");
exit(EXIT_FAILURE);
}

printf("Thread joined\n");

//销毁信号量对象
sem_destroy(&bin_sem);

exit(EXIT_SUCCESS);
}

void *thread_function(void *arg)
{
sem_wait(&bin_sem);//将信号量值减一。

while(strncmp("end",work_area,3))
{
printf("You input %d characters\n",strlen(work_area) - 1);
sem_wait(&bin_sem);
}

pthread_exit(NULL);//线程终止执行
}

运行结果:

请输入图片描述

发现被创建的新线程重复输出多次~这是为什么呢?问题出在哪里?

Linux 多线程

sybdcz 11 years, 9 months ago

45行和53行的代码是主要错误,那是多余的。
你的主线程已经在if-else里面增加了一次信号量的值,但是又在53行代码那里再增加一次,而另外一个线程执行一次循环才减少一次信号量的值。所以,当另外一个线程执行了一次循环之后,再次运行到81行代码时,它会发现信号量值大于0,从而将信号量值减一之后并再次循环,所以你会看到多次输出的结果。
至于45行代码那里也是多余的,当你输入FAST之后,先调用了一次sem_post,然后在下一次循环到45行代码那里再调用一次sem_post,这又增加了一次信号量的值,所以同理。

另外,线程函数thread_fuction有点逻辑小错误,最好用do-while,这样就可以只调用一个sem_wait了。

依文陵祈呀 answered 11 years, 9 months ago

Your Answer