2021SC@SDUSC
项目环境:- 树莓派4b
- Ubuntu Desktop 21.04
本实验中,使用多线程实现统计文本单词的功能。在统计时,凡是一个非字母或数字的字符跟在字母或数字的后面,那么这个字母或数字就是单词的结尾 。允许线程使用互斥锁来修改临界资源,确保线程间的同步与协作。若两个线程需要安全地共享一个公共计数器,需要把公共计数器加锁。
#include#include #include #include #include #include pthread_mutex_t f_mutex; FILE *fp1,*fp2; char ch; int count=0; void *pthread_function1(void *arg) { //sleep(1); fp1=fopen("1.txt","r"); if(!fp1) { printf("Open file failed!"); } while((ch=fgetc(fp1))!=EOF) { if((ch>='a'&&ch<='z')||(ch>='0'&&ch<='9')) continue; pthread_mutex_lock(&f_mutex); count++; pthread_mutex_unlock(&f_mutex); } } void *pthread_function2(void *arg) { //sleep(1); fp2=fopen("2.txt","r"); if(!fp2) { printf("Open file2 failed!"); } while((ch=fgetc(fp2))!=EOF) { if((ch>='a'&&ch<='z')||(ch>='0'&&ch<='9')) continue; pthread_mutex_lock(&f_mutex); count++; pthread_mutex_unlock(&f_mutex); } } int main() { pthread_t a,b; int res; res=pthread_mutex_init(&f_mutex,NULL); if(res!=0) { perror("Mutex initialization failedn"); exit(EXIT_FAILURE); } res=pthread_create(&a,NULL,pthread_function1,NULL); if(res!=0) { perror("Thread creation failedn"); exit(EXIT_FAILURE); } res=pthread_create(&b,NULL,pthread_function2,NULL); if(res!=0) { perror("Thread creation failedn"); exit(EXIT_FAILURE); } res=pthread_join(a,NULL); if(res!=0) { perror("Thread join failedn"); exit(EXIT_FAILURE); } res=pthread_join(b,NULL); if(res!=0) { perror("Thread join failedn"); exit(EXIT_FAILURE); } printf("There have %d words in two filesn",count); pthread_mutex_destroy(&f_mutex); return 0; }
如上所示,建立互斥信号量和两个文件指针,我们创建两个子线程,并分别以字符为单位对文本文件进行读取。测试文件为1.txt和2.txt。
可以看到线程统计出了两个文本文件中单词的个数。
哲学家就餐问题:在进程同步互斥中,哲学家就餐是另一个十分经典的算法,下面分析该算法。该算法有着很多种不同的实现方法,代码中实现一种最为常用的,即至多四个人同时拿左边的筷子,保证至少有一个人可以进餐,最终释放筷子使更多的人进餐。 定义了一个变量room使得最多只允许四个哲学家同时进餐,避免死锁 。
#include#include #include #include #include #include #include #include #define MAX_BUFFER_SIZE 5 #define SHM_MODE 0600 #define SEM_MODE 0600 #define mutex 5 #define true 1 #define room 6 int chopstick[5] = {0,1,2,3,4}; int sem_id = -1; pid_t philosopher; //P *** 作 void Wait(int sem_id,int sem_num) { struct sembuf buf; buf.sem_num = sem_num; buf.sem_op = -1; buf.sem_flg = SEM_UNDO; if(semop(sem_id,&buf,1) < 0) { perror("wait failed"); exit(1); } } //V操作 void Signal(int sem_id,int sem_num) { struct sembuf buf; buf.sem_num = sem_num; buf.sem_op = 1; buf.sem_flg = SEM_UNDO; if(semop(sem_id,&buf,1) < 0) { perror("signal failed"); exit(1); } } void think(int i) { printf("the philosopher of %d is thinking(pid is %d)n",i,getpid()); } void eat(int i) { printf("the philosopher of %d is eating(pid is %d)n",i,getpid()); } void Philosophers1(int sem_id,int i) { int j; for(j=0;j<2;j++){ think(i); Wait(sem_id,room); Wait(sem_id,chopstick[i]); Wait(sem_id,chopstick[(i+1)%5]); eat(i); Signal(sem_id,chopstick[i]); Signal(sem_id,chopstick[(i+1)%5]); printf("the process of %d(pid is %d,ppid is %d)has finished eatingn",i,getpid(),getppid()); Signal(sem_id,room); fflush(stdout); } exit(0); } int main() { int i = 0; if((sem_id = semget(IPC_PRIVATE,7,SEM_MODE)) < 0) { perror("create semaphore failed! n"); exit(1); } if(semctl(sem_id,mutex,SETVAL,1) == -1) { perror("sem set value error! n"); exit(1); } for(i=0;i<5;i++){ if(semctl(sem_id,chopstick[i],SETVAL,1) == -1) { perror("sem set value error! n"); exit(1); } } if(semctl(sem_id,room,SETVAL,4) == -1) { perror("sem set value error! n"); exit(1); } for(i=0;i<5;i++){ philosopher = fork(); if(philosopher < 0){ perror("the fork failed"); exit(1); } else if(philosopher == 0){ Philosophers1(sem_id,i); } } while (wait(0) != -1); shmctl(sem_id,IPC_RMID,0); printf("finish!!!n"); fflush(stdout); exit(0); return 0; }
在上述程序中,首先初始化筷子的信号量,同时初始化 room ,保证最多四个哲学家进餐。 对每一个哲学家在进餐之前进行如下原子 *** 作:
Wait(room), Wait(chopstick[i]), Wait(chopstick[(i+1)%5]) Signal(chopstick[i]), Signal(chopstick[(i+1)%5]), Signal(room)
若出现四个哲学家同时拿起了左手边的筷子,则第五个人必须等待,直到他两边的筷子空闲才可以进行进餐,这样就避免了哲学家在进餐过程中出现饥饿现象,也就是死锁。哲学家开始进餐。删除信号量和共享内存,释放空间。
下面是运行结果:
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)