[设计目的]
1. 学习并掌握多线程编程的基本概念和技巧;
2. 理解并应用互斥锁(mutex)来同步线程间的操作;
3. 设计并实现一个能够并行处理文件的单词统计工具。
[设计要求]
在操作系统当中,实现一个多线程程序,能够同时对两个文本文件进行单词统计。
在操作系统中,确保线程安全,避免在统计过程中出现数据竞争。
[设计思想及内容]
设计思想是通过创建两个线程,每个线程负责读取并统计一个文件中的单词数量。使用互斥锁来同步对共享变量total的访问,确保统计结果的正确性。
[数据结构设计]
total_words: 用于存储两个文件中单词总数的全局变量。
counter_clock: 互斥锁,用于同步对total变量的访问
total:用于存储统计总的文件中的单词总数的全局变量
补充命令
可能有的小伙伴不记得一些命令了,这里我稍微写一下(以我的文件world_total为例)
vim word_total.c 还有两个文本文件:vim word1.txt 和vim word2.txt
gcc word_total.c -o word_total
./word_total ./word1.txt ./word2.txt
[程序源码]
#include <stdio.h>
#include <pthread.h>//POSIX线程库,用于创建和管理线程
//字符串类型函数库,用于判断字符是否为字母或者数字
#include <ctype.h>
#include <stdlib.h> //标准库,提供一些通用函数,如exit()
//用于统计总的单词数
int total=0;
//定义互斥锁
//声明并初始化一个互斥锁,用于同步对total_words变量的访问。
pthread_mutex_t counter_clock=PTHREAD_MUTEX_INITIALIZER;
int main(int ac,char *av[])
{
void *count_words(void *);
//如果参数个数不等于三个,则打印提示后退出程序
//三个是因为程序名、两个文件名
if(ac!=3)
{
printf("Usage:%s file1 file2\n",av[0]);
exit(1);
}
//创建两个线程tidp1和tidp2,分别用于处理两个文件的单词统计
pthread_t tidp1,tidp2;
int e1,e2;
//建立两个线程tidp1 tidp2
e1=pthread_create(&tidp1,NULL,count_words,av[1]);
e2=pthread_create(&tidp2,NULL,count_words,av[2]);
//使用pthread_join等待两个线程完成。
//让线程tidp1和tidp2进入等待状态
pthread_join(tidp1,NULL);
pthread_join(tidp2,NULL);
printf(“\n”);
printf(“total = %d”,total);
return 0;
}
//这是一个线程函数,由main函数中的pthread_create调用
void *count_words(void *f)
{
char *filename=(char *)f;
FILE *fp;
int c,prevc='\0';
int total_words=0;
if((fp=fopen(filename,"r"))!=NULL){
while((c=getc(fp))!=EOF)
{
//使用isalnum函数判断字符是否为字母或数字
if(!isalnum(c) && isalnum(prevc)){
//当遇到一个非字母数字字符且前一个字符是字母数字时,认为发现了一个单词//的边界。此时:
//1使用pthread_mutex_lock锁定互斥锁,以确保线程安全地增加单词计数。
//2增加total_words计数。
//3使用pthread_mutex_unlock解锁互斥锁(类似于pv原语)
pthread_mutex_lock(&counter_clock);
total_words++;
pthread_mutex_unlock(&counter_clock);
}
prevc=c;
}
fclose(fp);
printf("total_words=%d\n",total_words);
pthread_mutex_lock(&counter_clock);
total+=total_words;
pthread_mutex_unlock(&counter_clock);
}else{
perror(filename);
}
return NULL;
}
[设计实现展示(附截图说明)]
Word1.txt文件中的内容
Word2.txt文件中的内容
编译链接并执行程序,我们可以看到文件一中有222个单词,文件二中有346个单词
改进之后加了个总的计数器
总的单词数为568
[课程设计出现问题及解决方法]
遇到的问题:
1互斥锁使用不当
问题:在count_words函数中,第一次使用互斥锁是将一个文件中的所有单词都统计完成才会放开,这样会造成一个进程统计,而另一个进程只能等待的现象,就算被统计的进程暂时空闲,也不会放开互斥锁,造成志愿的浪费
解决方法:
在每一个统计时都加锁,既保证了文件的安全性,互斥型号量不会被随意更改,又使得CPU不会空闲,充分利用CPU资源
【参考资料】
[1] https://blog.youkuaiyun.com/zmxiangde_88/article/details/7998458