Linux并行计算

Linux并行计算,第1张

Linux并行计算

2021SC@SDUSC

项目环境:
  1. 树莓派4b
  2. 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)

若出现四个哲学家同时拿起了左手边的筷子,则第五个人必须等待,直到他两边的筷子空闲才可以进行进餐,这样就避免了哲学家在进餐过程中出现饥饿现象,也就是死锁。哲学家开始进餐。删除信号量和共享内存,释放空间。

下面是运行结果:

 

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5619201.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-15
下一篇 2022-12-15

发表评论

登录后才能评论

评论列表(0条)

保存