zoukankan      html  css  js  c++  java
  • C语言实现PV操作

    C语言实现PV操作典型程序

    PV操作是典型的同步机制之一。用一个信号量与一个消息联系起来,当信号量的值为0时,表示期望的消息尚未产生;当信号量的值非0时,表示期望的消息已经存在。用PV操作实现进程同步时,调用P操作测试消息是否到达,调用V操作发送消息。

    概念

    临界区**指的是一个访问共用资源(例如:共用设备或是共用存储器)的程序片段,而这些共用资源又无法同时被多个线程访问的特性。

    临界区调度原则:

    1、如果有若干进程要求进入空闲的临界区,一次仅允许一个进程进入。

    2、任何时候,处于临界区内的进程不可多于一个。如已有进程进入自己的临界区,则其它所有试图进入临界区的进程必须等待。

    3、进入临界区的进程要在有限时间内退出,以便其它进程能及时进入自己的临界区。

    4、如果进程不能进入自己的临界区,则应让出CPU,避免进程出现“忙等”现象。

    信号量(semaphore): 可用于进程间同步也可用于同一个进程间的线程同步。

    信号量有一个使用计数器,这个使用计数器,是信号量的最大资源计数和当前资源计数的差值。

    计数器的值大于0时,表示当前可用资源个数。

    计数器的值小于0时,表等待使用资源的进程个数。

    计数器的值为0则既没有可用资源也没有等待资源的进程

    假设S的为信号量的计数器的值:

    P操作:执行一次P操作意味着请求分配一个单位的资源,因此S的值减1,当S<0时,表示已经没有可用资源,请求者必须等待别的进程释放该类资源,它才能继续运行。
    V操作:执行一次V操作意味着释放一个资源,因此S的值加1,当S<0,表示有某些进程正在等待资源,因此要唤醒一个等待状态的进程,使之继续运行。

    实例

    PV操作解决问题可以套用一个固定的代码demo~就是一个while里套三个部分:开头一个P结尾一个V中间是临界区,

    1587368244396

    1587368291998

    使用PV操作来解决问题:爸爸放苹果,女儿拿苹果,妈妈放橘子,儿子拿橘子。

    由题可以看出需要4个进程,爸爸和妈妈的进程需要执行放的操作,我们分别套用模型即可

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <pthread.h>
    #include<semaphore.h>
    
    
    #define P sem_wait
    #define V sem_post 
    #define full_apple &fullA
    #define full_orange &fullB
    #define empty &empty_aha
    
    
    sem_t fullA;
    sem_t fullB;
    sem_t empty_aha;
    int num=0; 
    
    
    
    void* Dad(void *p)
    {
        while(num<50)
        { 
            P(empty);  
    	    num++;
            printf("老爸放了个苹果%d
    ",num);
            V(full_apple);
        }
    }
    
    
    void* Dangter(void *p)
    {
        while(num<50)
        {
            P(full_apple);
    		num++;               
             printf("女儿吃了个苹果%d
    ",num);
            V(empty);
        }
    }
    
    void* Mum(void *p)
    {
        while(num<50)
        { 
            P(empty);  
    	    num++;
            printf("老妈放了个橘子%d
    ",num);
            V(full_orange);
        }
    }
    
    
    void* Son(void *p)
    {
        while(num<50)
        {
            P(full_orange);
    		num++;               
            printf("儿子吃了个橘子%d
    ",num);
            V(empty);
        }
    }
    
    int main()
    {
        
        sem_init(full_apple, 0, 0);
        sem_init(full_orange, 0, 0);   
        sem_init(empty, 0, 1);   
     
        pthread_t tid0;
        pthread_t tid1;
        pthread_t tid2;
        pthread_t tid3;
        pthread_create(&tid0, NULL, Dad, NULL);
        pthread_create(&tid1, NULL, Mum, NULL);
        pthread_create(&tid2, NULL, Son, NULL);
        pthread_create(&tid3, NULL, Dangter, NULL);
        getchar();
        pthread_exit(0);
        return 0;
    }
    
    
  • 相关阅读:
    XCOPY命令默认忽略隐藏文件
    SSAS : 如果在MDX查询中没有指定度量值,那么会怎么处理
    .NET : 存取BLOB数据(Oracle)
    jQuery.getJSON(url, [data], [callback])
    SSAS : 在SSAS 2008的自定义存储过程中取得当前用户名
    再来谈谈json
    .NET :在Visual Studio的不同Tab之间切换
    SSAS : 从现有多维数据集创建挖掘结构
    SQL Server : Browser服务是干什么的
    SSAS2008 : 全新的可扩展插件架构
  • 原文地址:https://www.cnblogs.com/lightice/p/12738215.html
Copyright © 2011-2022 走看看