(计算机操作系统)wait操作和signal操作什么意思?

(计算机操作系统)wait操作和signal操作什么意思?,第1张

规定在拿到左侧的筷子后,先检查右面的筷子是否可用。如果不可用,则先放下左侧筷子, 等一段时间再重复整个过程。 分析:当出现以下情形,在某一个瞬间,所有的哲学家都同时启动这个算法,拿起左侧的筷 子,而看到右侧筷子不可用,又都放下左侧筷子,等一会儿,又同时拿起左侧筷子……如此 这样永远重复下去。对于这种情况,所有的程序都在运行,但却无法取得进展,即出现饥饿, 所有的哲学家都吃不上饭。 (2) 描述一种没有人饿死(永远拿不到筷子)算法。 考虑了四种实现的方式(A、B、C、D): A.原理:至多只允许四个哲学家同时进餐,以保证至少有一个哲学家能够进餐,最终总会释 放出他所使用过的两支筷子,从而可使更多的哲学家进餐。以下将room 作为信号量,只允 许4 个哲学家同时进入餐厅就餐,这样就能保证至少有一个哲学家可以就餐,而申请进入 餐厅的哲学家进入room 的等待队列,根据FIFO 的原则,总会进入到餐厅就餐,因此不会 出现饿死和死锁的现象。 伪码: semaphore chopstick[5]=semaphore room=4void philosopher(int i) } B.原理:仅当哲学家的左右两支筷子都可用时,才允许他拿起筷子进餐。 方法1:利用AND 型信号量机制实现:根据课程讲述,在一个原语中,将一段代码同时需 要的多个临界资源,要么全部分配给它,要么一个都不分配,因此不会出现死锁的情形。当 某些资源不够时阻塞调用进程由于等待队列的存在,使得对资源的请求满足FIFO 的要求, 因此不会出现饥饿的情形。 伪码: semaphore chopstick[5]=void philosopher(int I) } 方法2:利用信号量的保护机制实现。通过信号量mutex对eat()之前的取左侧和右侧筷 子的操作进行保护,使之成为一个原子操作,这样可以防止死锁的出现。 伪码: semaphore mutex = 1 semaphore chopstick[5]=void philosopher(int I) }

#include<stdio.h>  

#include<stdlib.h>  

#include<unistd.h>  

#include<semaphore.h>  

#include<pthread.h>  

  

#define PRODUCER 10//生产者数量  

#define CONSUMER 8//消费者数量  

#define BUFFER 20//缓冲区数量  

  

sem_t empty,full//同步信号量  

pthread_mutex_t mutex//互斥信号量  

int buffer[BUFFER] //缓冲区  

  

int producer_id=0,consumer_id=0//生产者消费者ID  

int index_in=0,index_out=0//生产者 消费者 存放 消费的位置  

  

void print()//输出缓冲区  

{  

   int i  

   printf("Buffer:\n")  

   for(i=0i<20i++)  

   {  

      printf("___")  

   }  

   printf("\n")  

   for(i=0i<20i++)  

      printf("|%d|",buffer[i])  

   printf("\n")  

   for(i=0i<20i++)  

   {  

      printf("———")  

   }   

   printf("\n")  

}  

void *Producer()//生产者函数  

{  

   int ID=++producer_id  

  

   while(1)  

   {  

     sleep(3)  

     sem_wait(&empty)  

     pthread_mutex_lock(&mutex)  

     index_in=index_in%BUFFER  

  

     printf("Producer %d in %d.\n",ID,index_in)  

     buffer[index_in]=1//缓冲区置0  

     print()//输出缓冲区情况  

     index_in++  

     pthread_mutex_unlock(&mutex)  

     sem_post(&full)  

   }  

}  

void *Consumer()//消费者函数  

{  

   int ID=++consumer_id  

  

   while(1)  

   {  

     sleep(3)  

     sem_wait(&full)  

     pthread_mutex_lock(&mutex)  

     index_out=index_out%BUFFER  

  

     printf("\033[0134mConsumer %d in %d\033[0m\n",ID,index_out)  

     buffer[index_out]=0//缓冲区置0  

     print()//输出缓冲区情况  

     index_out++  

     pthread_mutex_unlock(&mutex)  

     sem_post(&empty)  

   }  

}  

  

int main()  

{  

   //freopen("text.txt","w",stdout)  

   int rthread[18],i  

   pthread_t producer[PRODUCER]//生产者  

   pthread_t consumer[CONSUMER]//消费者  

  

   int sinit1=sem_init(&empty,0,BUFFER)//初始化同步信号量  

   int sinit2=sem_init(&full,0,0)  

   int minit =pthread_mutex_init(&mutex,NULL)//初始化互斥信号量  

   if(sinit1 && sinit2)  

   {  

     printf("sem initialize failed /n")  

     exit(1)  

   }  

   if(minit)  

   {  

     printf("sem initialize failed /n")  

     exit(1)  

   }  

   for(i=0i<PRODUCERi++)//创建生产者线程  

   {  

      rthread[i]=pthread_create(&producer[i], NULL, Producer, NULL)  

      if(rthread[i])  

      {  

          printf("producer %d create failed /n", i)  

          exit(1)  

      }  

   }  

   for(i=0i<CONSUMERi++)//创建消费者线程  

   {  

      rthread[i]=pthread_create(&consumer[i], NULL, Consumer,NULL)  

      if(rthread[i])  

      {  

          printf("consumer %d create failed /n", i)  

          exit(1)  

      }  

   }  

   for(i=0i<PRODUCERi++)//销毁生产者线程  

   {  

      pthread_join(producer[i],NULL)  

   }  

   for(i=0i<CONSUMERi++)//销毁生产者线程  

   {  

      pthread_join(consumer[i],NULL)  

   }  

   exit(0)  

}

下,应该差不多

一、如何建立线程

用到的头文件

(a)pthread.h

(b)semaphore.h

(c) stdio.h

(d)string.h

定义线程标识

pthread_t

创建线程

pthread_create

对应了一个函数作为线程的程序段

注意的问题

要保证进程不结束(在创建线程后加死循环)

在线程中加入While(1)语句,也就是死循环,保证进程不结束。

二、控制线程并发的函数

sem_t:信号量的类型

sem_init:初始化信号量

sem_wait:相当于P操作

sem_post:相当于V操作

三、实现原形系统

父亲、母亲、儿子和女儿的题目:

桌上有一只盘子,每次只能放入一只水果。爸爸专放苹果,妈妈专放橘子,一个儿子专等吃盘子中的橘子,一个女儿专等吃盘子中的苹果。分别用P,V操作和管程实现

每个对应一个线程

pthread_t father father进程

pthread_t mother mother进程

pthread_t son son进程

pthread_t daughter daughter进程

盘子可以用一个变量表示

sem_t empty

各线程不是只做一次,可以是无限或有限次循环

用While(1)控制各线程无限次循环

输出每次是那个线程执行的信息

printf("%s\n",(char *)arg)通过参数arg输出对应线程执行信息

编译方法

gcc hex.c -lpthread

生成默认的可执行文件a.out

输入./a.out命令运行

查看结果:程序连续运行显示出

father input an apple.

daughter get an apple.

mother input an orange.

son get an orange.

mother input an orange.

son get an orange.

………………..

四、程序源代码

#include <stdio.h>

#include<string.h>

#include <semaphore.h>

#include <pthread.h>

sem_t empty //定义信号量

sem_t applefull

sem_t orangefull

void *procf(void *arg) //father线程

{

while(1){

sem_wait(&empty)//P操作

printf("%s\n",(char *)arg)

sem_post(&applefull)//V操作

sleep(7)

}

}

void *procm(void *arg) //mother线程

{

while(1){

sem_wait(&empty)

printf("%s\n",(char *)arg)

sem_post(&orangefull)

sleep(3)

}

}

void *procs(void *arg) //son线程

{

while(1){

sem_wait(&orangefull)

printf("%s\n",(char *)arg)

sem_post(&empty)

sleep(2)

}

}

void *procd(void *arg) //daughter线程

{

while(1){

sem_wait(&applefull)

printf("%s\n",(char *)arg)

sem_post(&empty)

sleep(5)

}

}

main()

{

pthread_t father //定义线程

pthread_t mother

pthread_t son

pthread_t daughter

sem_init(&empty, 0, 1) //信号量初始化

sem_init(&applefull, 0, 0)

sem_init(&orangefull, 0, 0)

pthread_create(&father,NULL,procf,"father input an apple.") //创建线程

pthread_create(&mother,NULL,procm,"mother input an orange.")

pthread_create(&daughter,NULL,procd,"daughter get an apple.")

pthread_create(&son,NULL,procs,"son get an orange.")

while(1){} //循环等待

}

另外,站长团上有产品团购,便宜有保证


欢迎分享,转载请注明来源:夏雨云

原文地址:https://www.xiayuyun.com/zonghe/354154.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-09
下一篇2023-05-09

发表评论

登录后才能评论

评论列表(0条)

    保存