一、实验目的:
学习线程的编程和同步。
二、实验要求:
1、程序语法
philosopher_th <N> [ -t <time> ]
N是哲学家的个数(N >= 2)。
time是哲学家进餐和沉思的持续时间值,缺省为2秒。
2、哲学家的编号为0 ~ N-1,分别用N个线程独立模拟。
3、程序的输出要简洁,例如,当编号为3的哲学家在进餐时,就打印:
philosopher 3 is eating
而当他在沉思时,则打印:
philosopher 3 is thinking
不要输出其他任何信息。
4、使用pthread的semaphore.h提供的信号量同步线程。
5、程序一直运行,直到人为地终止它(如按Ctrl-C或Ctrl-\)。不允许出现僵尸进程。
三、实验设计:
该实验和实验四类似,只是用文件来定义N把叉子,其文件名可以按如下方式说明:static sem_t *forks;forks = (sem_t *)malloc( N * sizeof(sem_t));N个哲学家可以用for循环创建N个线程,在函数philosopher_th中实现哲学家思考nsecs,然后拿起叉子,进餐nsecs后,放下叉子。在主线程中要用pthread_join()等待进程终止。
四、实验程序:
#include "apue.h"
#include<semaphore.h>
#include<pthread.h>
static sem_t *forks;
static int nsecs, N;
void* philosopher_th(void *n)
{
int i = (int) n;
while(1)
{
if(i==N-1)//最后一个哲学家使用第N-1把叉子和第0把叉子
{
printf("philosopher %d isthinking\n",i);
sleep(nsecs);
sem_wait(&forks[0] );//sem_wait函数的作用是从信号量的值减去一个“1”
sem_wait(&forks[i] );
printf("philosopher %d is eating\n",i);
sleep(nsecs);
sem_post(&forks[0] );//sem_post函数的作用是给信号量的值加上一个“1”
sem_post(&forks[i] );
}
else
{
printf("philosopher %d is thinking\n",i);
sleep(nsecs);
sem_wait(&forks[i]);
sem_wait(&forks[i+1]);
printf("philosopher %d is eating\n",i);
sleep(nsecs);
sem_post(&forks[i]);
sem_post(&forks[i+1]);
}
}
}
int
main(int argc,char *argv[])
{
inti,status;
N=atoi(argv[1]);
forks=(sem_t *) malloc(N*sizeof(sem_t));// 分配N个信号量
for(i=0; i<N;i++)
sem_init(forks + i, 0, 1); // 初始化信号量
if(argc==2)
nsecs=2;//时间缺省值
elseif(argc==4&&strcmp("-t",argv[2])==0)
nsecs=atoi(argv[3]);
elseerr_sys("Input error");
pthread_ttpid;
for(i= 0; i < N; i++)
{
status = pthread_create(&tpid, NULL, philosopher_th, (void *) i);
if(tpid < 0 )
err_quit("can't creatthread:%s\n",streeror(status));
}
pthread_join(tpid, NULL);
exit(0);
}
五、实验结果:
程序执行过程:
编译:gcc philosopher_th.c error2e.c -ophilosopher_th -lpthread
运行过程:输入./philosopher_th 5
输入:./philosopher_th 5 -t 3