首页 > 系统相关 >4.进程同步与互斥

4.进程同步与互斥

时间:2023-12-20 16:46:00浏览次数:24  
标签:哲学家 进程同步 signal chopstick 互斥 筷子 缓冲区 wait

  1. 生产者消费者问题

    一组生产者进程和一组消费者进程共享一个初始为空,大小为n的缓冲区。当缓冲区没满时,生产者才能把消息放入缓冲区,否则必须等待,只有缓冲区不空时,消费者才能从中取出消息,否则必须等待。由于缓冲区是临界资源,它只允许一个生产者放入消息,或一个消费者从中取出消息。

    semaphore mutex=1; //临界区互斥信号量
    semaphore empty=n; //空闲缓冲区
    semaphore full=0; //满缓冲区
    int in=0,out=0;
    item buffer[n];
    
    //生产者
    producer()
    {
    	while(1){
             produce an item nextp; //生产产品
    		wait(empty); //获取空缓冲区
    		wait(mutex); //进入临界区
    		buffer[in]=nextp; //数据放入临界区
    		in=(int+1)%n; 
    		signal(mutex);  //离开临界区,释放互斥信号量
    		signal(full);  //满缓冲区数+1
    	}
    }
    
    //消费者
    consumer()
    {
    	while(1){
    		wait(full); //获取满缓冲区
    		wait(mutex); //进入临界区
    		nextc=buffer[out]; //从缓冲区取数据
    		out=(out+1)%n;
    		signal(mutex); //离开临界区,释放互斥信号量
    		signal(empty); //空缓冲区数+1
             consume the item in nextc; //消费产品
    	}
    }
    
  2. 读者写者问题

    有读写两组进程,共享一个文件,

    ①多个读者可同时访问文件

    ②但多个写者不能同时访问文件

    ③写者和读者不能同时访问文件

    semaphore rmutex=1; //保护counter变量的互斥信号量
    semaphore wmutex=1; //保证读者和写者互斥访问文件
    int counter=0;  //记录当前读者数量
    
    //读者
    reader(){
        while(1){
            wait(rmutex);  //互斥访问counter变量
            if(counter==0)wait(wmutex);  //当第一个读者时,阻止写进程写
            couter++;  //计数器+1
            signal(rmutex);  //释放互斥变量counter
            
            reading  //读操作 
                
            wait(rmutex);  //互斥访问counter变量
            counter--;  //计数器-1
            if(counter==0)signal(wmutex); //当最后一个读者时,允许写进程写
            signal(rmutex);  //释放互斥变量counter
        }	
    }
    
    
    
    //写者
    writer(){
    	while(1){
            wait(wmutex);  //互斥访问共享文件
            writing  //写操作
            signal(wmutex);	//释放共享文件
    	}
    }
    
    
    
  3. 哲学家就餐

    有五个哲学家围在一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五只筷子,他们的生活方式是交替的进行思考和进餐。平时,一个哲学家进行思考,饥饿时便试图取用其左右最靠近他的筷子,只有在他拿到两支筷子时才能进餐。进餐完毕后,放下筷子继续思考。

    • 由问题描述我们可以知道,一共有五个哲学家,也就是五个进程;五只筷子,也就是五个临界资源;因为哲学家想要进餐,必须要同时获得左边和右边的筷子,这就是要同时进入两个临界区(使用临界资源),才可以进餐。
    semaphore chopstick[5] = {1,1,1,1,1}; 		//初始化信号量
    
    void P(){
      while(1)
      {
        think;			//思考
        wait(chopstick[i]);//判断哲学家左边的筷子是否可用
        wait(chopstick[(i+1)%5]);//判断哲学家右边的筷子是否可用
        
        eat;		//进餐
        
        signal(chopstick[i]); //退出临界区,允许别的进程操作缓冲池
        signal(chopstick[(i+1)%5]); //缓冲池中非空的缓冲区数量加1,可以唤醒等待的消费者进程
      }
    }
    
    

    问题:如果考虑到并发问题,五个哲学家同时拿起了左边的筷子,此时,五只筷子立刻都被占用了,没有可用的筷子了,当所有的哲学家再想拿起右边筷子的时候,因为临界资源不足,只能将自身阻塞,而所有的哲学家全部都会阻塞,并且不会释放自己手中拿着的左边的筷子,因此就会一直处于阻塞状态,无法进行进餐并思考。

    解决方法:

    1. 至多只允许有四位哲学家同时去拿左边的筷子,最终能保证至少有一位哲学家能够进餐,并在用餐完毕后能释放他占用的筷子,从而使别的哲学家能够进餐
    2. 仅当哲学家的左、右两支筷子可用时,才允许他拿起筷子
    3. 规定奇数号哲学家先拿他左边的筷子,然后再去拿右边的筷子;而偶数号哲学家则相反

    方法1(增加一个信号量实现):

    semaphore chopstick[5] = {1,1,1,1,1}; 		//初始化信号量
    semaphore sm=4;
    
    void P(){
      while(1)
      {
        think;			//思考
        wait(sm);
        wait(chopstick[i]);//判断哲学家左边的筷子是否可用
        wait(chopstick[(i+1)%5]);//判断哲学家右边的筷子是否可用
        signal(sm);
        
        eat;		//进餐
        
        signal(chopstick[i]); //退出临界区,允许别的进程操作缓冲池
        signal(chopstick[(i+1)%5]); //缓冲池中非空的缓冲区数量加1,可以唤醒等待的消费者进程
      }
    }
    

    方法2(使用AND型信号量):

    semaphore chopstick[5] = {1,1,1,1,1}; 		//初始化信号量
    semaphore sm=4;
    
    void P(){
      while(1)
      {
        think;			//思考
        wait(chopstick[i],chopstick[(i+1)%5]); //判断哲学家左右筷子是否同时可用
        
        eat;
        signal(chopstick[i],chopstick[(i+1)%5]); //进餐完毕,释放哲学家占有的筷子
      }
    }
    

    方法3(添加判断来决定获取左、右筷子的顺序,规定偶数号哲学家先拿左手筷子,再拿右手筷子):

    semaphore chopstick[5] = {1,1,1,1,1}; 		//初始化信号量
    semaphore sm=4;
    
    void P(){
      while(1)
      {
        think;			//思考
        if(i%2==0){
        	wait(chopstick[i]); //判断哲学家左边的筷子是否可用
        	wait(chopstick[(i+1)%5]); //判断哲学家右边的筷子是否可用
    	}
    	else{
        	wait(chopstick[(i+1)%5]);  //判断哲学家右边的筷子是否可用
        	wait(chopstick[i]); //判断哲学家左边的筷子是否可用
    	}
        
        eat;
        signal(chopstick[i]); //释放左边筷子
       signal(chopstick[(i+1)%5]); //释放右边筷子
      }
    }
    

标签:哲学家,进程同步,signal,chopstick,互斥,筷子,缓冲区,wait
From: https://www.cnblogs.com/zzmxj/p/17892218.html

相关文章

  • FreeRTOS中信号量和互斥量背后的原理
    FreeRTOS是一个流行的嵌入式实时操作系统,提供了信号量和互斥量等同步机制来协调任务之间的访问共享资源。本文将深入探讨FreeRTOS中信号量和互斥量的背后原理,以及如何使用这些机制确保系统的稳定性和性能。1.信号量和互斥量的概念1.1信号量信号量是一种计数器,用于控制多个任务对......
  • FreeRTOS--互斥量
    示例源码基于FreeRTOSV9.0.0互斥量1.概述互斥量用于临界资源的保护,通过互斥量,多个任务对相同资源进行的访问操作是互斥的;互斥量的核心在于谁上锁,就由谁解锁,这只是约定,FreeRTOS并没有在代码上实现这一点;互斥量是一种特殊的信号量,也是一种特殊的队列;使用互斥量,需要开启宏con......
  • 协程与互斥锁: Kotlin Mutex的终极指南
    引言今天我们将深入研究Kotlin中的Mutex(互斥锁)原理以及在实际开发中的使用技巧。Mutex是多线程编程中的关键工具,它可以有效地解决多线程访问共享资源时可能发生的竞态条件问题。Mutex的基本原理Mutex是互斥锁的缩写,它是一种同步工具,用于保护共享资源,确保在任何时刻只有一个线程可以......
  • Wound/Wait死锁安全的互斥锁设计 【ChatgGPT】
    https://www.kernel.org/doc/html/v6.6/locking/ww-mutex-design.htmlWound/Wait死锁安全的互斥锁设计请先阅读通用互斥锁子系统,因为它也适用于等待/伤害互斥锁。WW-互斥锁的动机GPU执行的操作通常涉及许多缓冲区。这些缓冲区可以在不同的上下文/进程之间共享,在不同的内存域......
  • 通用互斥子系统 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/locking/mutex-design.html通用互斥子系统由[email protected]发起由[email protected]更新互斥锁是什么?在Linux内核中,互斥锁指的是一种特定的锁原语,它在共享内存系统上强制进行串行化,而不仅仅是指学术界......
  • 03_实验三_进程同步
    实验三进程同步实验目的使用EOS的信号量,编程解决生产者—消费者问题,理解进程同步的意义。调试跟踪EOS信号量的工作过程,理解进程同步的原理。修改EOS的信号量算法,使之支持等待超时唤醒功能(有限等待),加深理解进程同步的原理预备知识信号量机制问题:1.在双标志......
  • C++11 多线程并发 互斥量、条件变量和信号量
    互斥量Classesmutex(C++11)providesbasicmutualexclusionfacility(class)timed_mutex(C++11)providesmutualexclusionfacilitywhichimplementslockingwithatimeout(class)recursive_mutex(C++11)providesmutualexclusionfacili......
  • Redis缓存雪崩、击穿、穿透解释及解决方法,缓存预热,布隆过滤器 ,互斥锁
    Redis缓存雪崩、击穿、穿透解释及解决方法,缓存预热,布隆过滤器,互斥锁......
  • FreeRTOS(2):队列、信号量、互斥量
    1、队列 1.1数据传输方法任务之间如何传输数据 数据个数互斥措施阻塞-唤醒全局变量1无无环形缓冲区多个无无队列多个有有队列又称消息队列,是一种常用于任务间通信的数据结构,队列可以在任务与任务间、中断和任务间传递信息。为什么不使用全局变......
  • java线程:互斥锁与读写锁
    两种互斥锁机制:1、synchronized2、ReentrantLockReentrantLock是jdk5的新特性,采用ReentrantLock可以完全替代替换synchronized传统的锁机制,而且采用ReentrantLock的方式更加面向对象,也更加灵活,网上有很多关于对比两者锁方式的文章,这里就不多口舌了,大家baidu、google一下就水落石......