重新编译程序,此时运行结果如下:

当我们输入TEST时,主线程向子线程提供了两个输入,一个是来自键盘的输入,一个来自主线程复数据到msg中,然后从运行结果可以看出,运行出现了异常,没有处理和统计从键盘输入TEST的字符串而却对复制的数据作了两次处理。原因如上面所述。
五、解决此缺陷的方法
解决方法有两个,一个就是再增加一个信号量,让主线程等到子线程处理统计完成之后再继续执行;另一个方法就是使用互斥量。
下面给出用增加一个信号量的方法来解决该问题的代码,源文件名为semthread2.c,源代码如下:
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
//线程函数
void *thread_func(void *msg);
sem_t sem;//信号量
sem_t sem_add;//增加的信号量
#define MSG_SIZE 512
int main()
{
int res = -1;
pthread_t thread;
void *thread_result = NULL;
char msg[MSG_SIZE];
//初始化信号量,初始值为0
res = sem_init(&sem, 0, 0);
if(res == -1)
{
perror("semaphore intitialization failedn");
exit(EXIT_FAILURE);
}
//初始化信号量,初始值为1
res = sem_init(&sem_add, 0, 1);
if(res == -1)
{
perror("semaphore intitialization failedn");
exit(EXIT_FAILURE);
}
//创建线程,并把msg作为线程函数的参数
res = pthread_create(&thread, NULL, thread_func, msg);
if(res != 0)
{
perror("pthread_create failedn");
exit(EXIT_FAILURE);
}
//输入信息,以输入end结束,由于fgets会把回车(n)也读入,所以判断时就变成了“endn”
printf("Input some text. Enter 'end'to finish...n");
sem_wait(&sem_add);
while(strcmp("endn", msg) != 0)
{
if(strncmp("TEST", msg, 4) == 0)
{
strcpy(msg, "copy_datan");
sem_post(&sem);
//把sem_add的值减1,即等待子线程处理完成
sem_wait(&sem_add);
}
fgets(msg, MSG_SIZE, stdin);
//把信号量加1
sem_post(&sem);
//把sem_add的值减1,即等待子线程处理完成
sem_wait(&sem_add);
}
printf("Waiting for thread to finish...n");
//等待子线程结束
res = pthread_join(thread, &thread_result);
if(res != 0)
{
perror("pthread_join failedn");
exit(EXIT_FAILURE);
}
printf("Thread joinedn");
//清理信号量
sem_destroy(&sem);
sem_destroy(&sem_add);
exit(EXIT_SUCCESS);
}
void* thread_func(void *msg)
{
char *ptr = msg;
//把信号量减1
sem_wait(&sem);
while(strcmp("endn", msg) != 0)
{
int i = 0;
//把小写字母变成大写
for(; ptr[i] != ' '; ++i)
{
if(ptr[i] >= 'a' && ptr[i] <= 'z')
{
ptr[i] -= 'a' - 'A';
}
}
printf("You input %d charactersn", i-1);
printf("To Uppercase: %sn", ptr);
//把信号量加1,表明子线程处理完成
sem_post(&sem_add);
//把信号量减1
sem_wait(&sem);
}
sem_post(&sem_add);
//退出线程
pthread_exit(NULL);








