UNIX程序设计实验六 线程及其同步—哲学家问题

来源:互联网 发布:淘宝助理快递单模板 编辑:程序博客网 时间:2024/05/21 17:24

                                                   实验六 线程及其同步—哲学家问题


     学习线程的编程和同步。

二 实验要求:

   1、程序语法

philosopher_th   <N> [ -t  <time> ]

N是哲学家的个数(N >= 2)。time是哲学家进餐和沉思的持续时间值,缺省为2秒。

2、哲学家的编号为0 ~ N-1,分别用N个线程独立模拟。

3、程序的输出要简洁,例如,当编号为3的哲学家在进餐时,就打印:

philosopher 3 iseating

而当他在沉思时,则打印:

philosopher 3 isthinking

不要输出其他任何信息。

4、使用pthread的semaphore.h提供的信号量同步线程。

5、程序一直运行,直到人为地终止它(如按Ctrl-C或Ctrl-\)。不允许出现僵尸进程。

四实验程序

#include"apue.h"

#include<stdio.h>

#include<semaphore.h>

#include<pthread.h>

intmain(int argc,char * argv[])

{

   unsigned int n,time;

   int i;

 

   if(argc==2)

   {

      n=(unsigned int)atoi(argv[1]);

      time=2;

      printf("**  The default time is: %d  **\n",time);

      printf("**  The number of philosopher is %d  **\n",n);

   }

   elseif(argc==4&&(strcmp(argv[2],"-t"))==0)

   {

      n=(unsigned int)atoi(argv[1]);

      time=(unsigned int)atoi(argv[3]);

      printf("**  The design time is:%d  **\n",time);

      printf("**  The number of philosopher is %d  **\n",n);

   }

   else

   {

      printf("Usage:./philosopher N -ttime\n");

   }

   pthread_t tid[n];

   sem_t sem[n];

   for(i=0;i<n;i++)

   {   interr;

      err=sem_init(&sem[i],0,1);

      if(err!=0)

        printf("semaphore[i] initfailed\n");

   }

   void thinking(int i,int time)

   {

      printf("philosopher %d is thinking \n",i);

      sleep(time);

   }

   void eating(int i,int time)

   {

      printf("philosopher %d is eating \n",i);

      sleep(time);

   }

   void takefork(int i)

   {

      if(i==n-1)

      {

        sem_wait(&sem[0]);

        sem_wait(&sem[i]);

      }

      else

      {

        sem_wait(&sem[i]);

        sem_wait(&sem[i+1]);

      }

   }

   void putfork(int i)

   {

      if(i==n-1)

      {

        sem_post(&sem[0]);

        sem_post(&sem[i]);

      }

      else

      {

        sem_post(&sem[i]);

        sem_post(&sem[i+1]);

      }

     

}

   void *thr_fn(void * arg)

   {

      int i=(int) arg;

      sleep(i);

      while(1)

      {

        thinking(i,time);

        takefork(i);

        eating(i,time);

        putfork(i);

       

      }

}

   for(i=0;i<n;i++)

   {

      int err;

      err=pthread_create(&tid[i],NULL,thr_fn,(void*)i);

      if(err!=0)

        printf("can't create thread%d:%s\n",i,strerror(err));

   }

 while(1)

    pause;

}

四实验结果

  源程序名:thread_philosopher.c

  可执行程序名:thph

  编译方法:gccthread_philosopher.c error2e.c –o thph -lpthread

  结束方法:ctrl+c

 运行过程:

 

1.编译

   

2.实现第一种情况:(自己定义哲学家的个数,并且使用默认时间值)

例如:./thph 5


3.实现第二种情况:(自己定义哲学家个数和使用时间值)

例如:./thph 5 -t 3


五 实验小结

    通过本次实验,可以学到:信号量的数据类型为结构sem_t,它本质上是一个长整型的数。函数sem_init()用来初始化一个信号量。它的原型为:  

extern intsem_init __P ((sem_t *__sem, int __pshared, unsigned int __value));

sem为指向信号量结构的一个指针;pshared不为0时此信号量在进程间共享,否则只能为当前进程的所有线程共享;value给出了信号量的初始值。  

    函数sem_post( sem_t *sem )用来增加信号量的值。当有线程阻塞在这个信号量上时,调用这个函数会使其中的一个线程不在阻塞,选择机制同样是由线程的调度策略决定的。  

函数sem_wait( sem_t *sem )被用来阻塞当前线程直到信号量sem的值大于0,解除阻塞后将sem的值减一,表明公共资源经使用后减少。函数sem_trywait ( sem_t *sem )是函数sem_wait()的非阻塞版本,它直接将信号量sem的值减一。  

函数sem_destroy(sem_t *sem)用来释放信号量sem。 

信号量用sem_init函数创建的,下面是它的说明:
  #include<semaphore.h>
        int sem_init (sem_t *sem, intpshared, unsigned int value);

      这个函数的作用是对由sem指定的信号量进行初始化,设置好它的共享选项,并指定一个整数类型的初始值。pshared参数控制着信号量的类型。如果 pshared的值是0,就表示它是当前里程的局部信号量;否则,其它进程就能够共享这个信号量。我们现在只对不让进程共享的信号量感兴趣。 (这个参数受版本影响), pshared传递一个非零将会使函数调用失败。

  这两个函数控制着信号量的值,它们的定义如下所示:
  
  #include <semaphore.h>
        int sem_wait(sem_t * sem);
        int sem_post(sem_t * sem);
 
        这两个函数都要用一个由sem_init调用初始化的信号量对象的指针做参数。
        sem_post函数的作用是给信号量的值加上一个“1”,它是一个“原子操作”---即同时对同一个信号量做加“1”操作的两个线程是不会冲突的;而同时对同一个文件进行读、加和写操作的两个程序就有可能会引起冲突。信号量的值永远会正确地加一个“2”--因为有两个线程试图改变它。
        sem_wait函数也是一个原子操作,它的作用是从信号量的值减去一个“1”,但它永远会先等待该信号量为一个非零值才开始做减法。也就是说,如果你对一个值为2的信号量调用sem_wait(),线程将会继续执行,介信号量的值将减到1。如果对一个值为0的信号量调用sem_wait(),这个函数就会地等待直到有其它线程增加了这个值使它不再是0为止。如果有两个线程都在sem_wait()中等待同一个信号量变成非零值,那么当它被第三个线程增加一个“1”时,等待线程中只有一个能够对信号量做减法并继续执行,另一个还将处于等待状态。
          

原创粉丝点击