linux多线程实验报告.docx
《linux多线程实验报告.docx》由会员分享,可在线阅读,更多相关《linux多线程实验报告.docx(13页珍藏版)》请在冰豆网上搜索。
linux多线程实验报告
实验八Linux多线程实验
报告撰写人
专业班级
学号
姓名
完成时间
。
。
。
。
。
。
。
。
。
。
。
一、实验目的
1、了解什么是多线程,熟悉LINUX的多线程机制;
2、掌握利用信号处理Linux多线程的同步问题;
3、掌握利用信号量处理Linux多线程的互斥问题;
4、运用Linux多线程的同步机制和互斥机制实现生产者消费者的编程。
二、实验内容
1.“生产者-消费者”问题如下:
有一个有限缓冲区和两个线程:
生产者和消费者。
他们分别不停地把产品放入缓冲区、从缓冲区中拿走产品。
一个生产者在缓冲区满的时候必须等待,一个消费者在缓冲区空的时候也必须等待。
另外,因为缓冲区是临界资源,所以生产者和消费者之间必须互斥执行。
它们之间的关系如图1所示。
现在要求使用共享内存来模拟有限缓冲区,并且使用信号量来解决“生产者-消费者”问题中的同步和互斥问题。
1生产者和消费者问题描述
2.问题描述:
假设有五位哲学家围坐在一张圆形餐桌旁,做以下两件事情之一:
吃饭,或者思考。
吃东西的时候,他们就停止思考,思考的时候也停止吃东西。
餐桌中间有一大碗意大利面,每两个哲学家之间有一只餐叉。
因为用一只餐叉很难吃到意大利面,所以假设哲学家必须用两只餐叉吃东西。
他们只能使用自己左右手边的那两只餐叉。
请用Linux线程编程解决。
2哲学家进餐问题示意图
三、实验过程与结果
操作过程
错误
解决方法
实验1
步骤一:
编写的文件
在不同的编译器中for循环的用法不太一样,在这里最好不要使用for(inti=0;;)
最好在外声明inti在for循环里直接写i=0
步骤二:
编译代码并且运行代码
步骤三:
运行完毕后,显示以下代码:
生产者消费者先后生产数据以及取出数据,此程序中设置了两个消费者两个生产者,交替进行生产数据消费数据。
实验2
步骤一:
编写的文件
步骤二:
编译代码并且运行代码
步骤三:
实验代码
实验一:
#include<>
#include<>
#include<>
#include<>
#include
#include
#include
#include
#defineMAX_BUFFER_SIZE10
#defineSHM_MODE0600
#defineSEM_MODE0600
#defineSEM_FULL0
#defineSEM_EMPTY1
#defineMUTEX2
/*
#ifdefined(__GNU_LIBRARY__)&&!
defined(_SEM_SEMUN_UNDEFINED)
\n",i+1,c);
printf("-------------------------------------------------------------\n");
fflush(stdout);
sigSem(sem_id,MUTEX);
sigSem(sem_id,SEM_FULL);
}
\n",i+1,lt);
printf("-------------------------------------------------------------\n");
fflush(stdout);
sigSem(sem_id,MUTEX);
sigSem(sem_id,SEM_EMPTY);
}
//将共享段与进程之间解除连接
shmdt(shmptr);
exit(0);
}
}
//主进程最后退出
while(wait(0)!
=-1);
//将共享段与进程之间解除连接
shmdt(shmptr);
//对共享内存区执行控制操作
shmctl(shm_id,IPC_RMID,0);//当cmd为IPC_RMID时,删除该共享段
shmctl(sem_id,IPC_RMID,0);
printf("主进程运行结束!
\n");
fflush(stdout);
exit(0);
return0;
}
实验二:
#include
#include<>
#include<>
#include<>
#include<>
#include<>
#include<>
#defineN5//哲学家数量
#defineLEFT(i)(i+N-1)%N//左手边哲学家编号
#defineRIGHT(i)(i+1)%N//右手边哲家编号
#defineHUNGRY0//饥饿
#defineTHINKING1//思考
#defineEATING2//吃饭
#defineU_SECOND1000000//1秒对应的微秒数
pthread_mutex_tmutex;//互斥量
intstate[N];//记录每个哲学家状态
//每个哲学家的思考时间,吃饭时间,思考开始时间,吃饭开始时间
clock_tthinking_time[N],eating_time[N],start_eating_time[N],start_thinking_time[N];
//线程函数
void*thread_function(void*arg);
intmain()
{
pthread_mutex_init(&mutex,NULL);
pthread_ta,b,c,d,e;
//为每一个哲学家开启一个线程,传递哲学家编号
pthread_create(&a,NULL,thread_function,"0");
pthread_create(&b,NULL,thread_function,"1");
pthread_create(&c,NULL,thread_function,"2");
pthread_create(&d,NULL,thread_function,"3");
pthread_create(&e,NULL,thread_function,"4");
//初始化随机数种子
srand((unsignedint)(time(NULL)));
while
(1)
{
;
}
}
void*thread_function(void*arg)
{
char*a=(char*)arg;
intnum=a[0]-'0';//根据传递参数获取哲学家编号
intrand_time;
while
(1)
{
//关键代码加锁
pthread_mutex_lock(&mutex);
//如果该哲学家处于饥饿并且左右两位哲学家都没有在吃饭就拿起叉子吃饭
if(state[num]==HUNGRY&&state[LEFT(num)]!
=EATING&&state[RIGHT(num)]!
=EATING)
{
state[num]=EATING;
start_eating_time[num]=clock();//记录开始吃饭时间
eating_time[num]=(rand()%5+5)*U_SECOND;//随机生成吃饭时间
//输出状态
printf("state:
%d%d%d%d%d\n",state[0],state[1],state[2],state[3],state[4]);
//printf("%diseating\n",num);
}
elseif(state[num]==EATING)
{
//吃饭时间已到,开始思考
if(clock()-start_eating_time[num]>=eating_time[num])//
{
state[num]=THINKING;
//printf("%disthinking\n",num);
printf("state:
%d%d%d%d%d\n",state[0],state[1],state[2],state[3],state[4]);
start_thinking_time[num]=clock();//记录开始思考时间
thinking_time[num]=(rand()%10+10)*U_SECOND;//随机生成思考时间
}
}
elseif(state[num]==THINKING)
{
//思考一定时间后,哲学家饿了,需要吃饭
if(clock()-start_thinking_time[num]>=thinking_time[num])
{
state[num]=HUNGRY;
printf("state:
%d%d%d%d%d\n",state[0],state[1],state[2],state[3],state[4]);
//printf("%dishungry\n",num);
}
}
pthread_mutex_unlock(&mutex);
}
}
四、实验小结
生产者消费者问题(英语:
Producer-consumerproblem),也称有限缓冲问题(英语:
Bounded-bufferproblem),是一个多线程同步问题的经典案例。
该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。
生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。
与此同时,消费者也在缓冲区消耗这些数据。
该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。
1)关系分析。
生产者和消费者对缓冲区互斥访问是互斥关系,同时生产者和消费者又是一个相互协作的关系,只有生产者生产之后,消费者才能消费,他们也是同步关系。
2)整理思路。
这里比较简单,只有生产者和消费者两个进程,正好是这两个进程存在着互斥关系和同步关系。
那么需要解决的是互斥和同步PV操作的位置。
3)信号量设置。
信号量mutex作为互斥信号量,它用于控制互斥访问缓冲池,互斥信号量初值为1;信号量full用于记录当前缓冲池中“满”缓冲区数,初值为0。
信号量empty用于记录当前缓冲池中“空”缓冲区数,初值为n。