zoukankan      html  css  js  c++  java
  • Linux下多线程模拟停车场停车

    #include<stdio.h>
    #include<string.h>
    #include<unistd.h>
    #include<stdlib.h>
    #include<pthread.h>
    
    #define ONE_SECOND 1000000
    #define RANGE 10
    #define PERIOD 2
    #define NUM_THREADS 4
    
    typedef struct 
    {
        int *carpark;    //用一个数组来模拟停车场停车位
        int capacity;    //停车场的车辆容量
        int occupied;    //停车场现有的车辆数目
        int nextin;        //下一个进来的车的位置(用carpark数组代表的下标表示)
        int nextout;    //下一个取走的车的停车位置
        int cars_in;    //记录停车场进入车辆的总和
        int cars_out;    //记录从停车场开出去的车辆总和
        pthread_mutex_t lock;    //互斥量,保护该结构中的数据被线程互斥的方式使用
        pthread_cond_t space;    //条件变量    描述停车场是否有空位置
        pthread_cond_t car;        //条件变量    描述停车场是否有车
        pthread_barrier_t bar;    //线程屏障
    }cp_t;
    
    static void initialise(cp_t *cp,int size)
    {
        cp->occupied = cp->nextin = cp->nextout = cp->cars_in = cp->cars_out = 0;
        cp->capacity = size;
        cp->carpark = (int *)malloc(cp->capacity * sizeof(*cp->carpark));
        
        //初始化线程屏障,NUM_THREADS表示等待 NUM_THREADS=4个线程同步执行
        pthread_barrier_init(&cp->bar,NULL,NUM_THREADS);
        
        if(cp->carpark == NULL)
        {
            perror("malloc()");
            exit(1);
        }
        
        srand((unsigned int )getpid());
        
        pthread_mutex_init(&cp->lock,NULL);     //初始化停车场的锁
        pthread_cond_init(&cp->space,NULL);        //初始化描述停车场是否有空位的条件变量
        pthread_cond_init(&cp->car,NULL);        //初始化描述停车场是否有车的条件变量
    }
    
    static void* car_in_handler(void* carpark_in)
    {
        cp_t *temp;
        unsigned int seed;
        temp = (cp_t *)carpark_in;
    
        //pthread_barrier_wait 函数表示,线程已完成工作,等到其他线程赶来
        pthread_barrier_wait(&temp->bar);
        while(1)
        {
            //将线程挂起一段时间,模拟车辆到来的随机性
            usleep(rand_r(&seed) % ONE_SECOND);
            pthread_mutex_lock(&temp->lock);
            
            //循环等待知道有停车位
            while(temp->occupied == temp->capacity)
                pthread_cond_wait(&temp->space,&temp->lock);
    
            //插入一辆车,用随机数标识
            temp->carpark[temp->nextin] = rand_r(&seed) % RANGE;
    
            temp->occupied++;
            temp->nextin++;
            temp->nextin %= temp->capacity;
            temp->cars_in++;
    
            //可能有的人在等车可取,发送temp->car条件变量
            pthread_cond_signal(&temp->car);
            pthread_mutex_unlock(&temp->lock);
        }
    
        return ((void*)NULL);
    }
    
    static void* car_out_handler(void *carpark_out)
    {
        cp_t *temp;
        unsigned int seed;
        temp = (cp_t *)carpark_out;
        pthread_barrier_wait(&temp->bar);
        for(;;)
        {
            usleep(rand_r(&seed) % ONE_SECOND);
    
            pthread_mutex_lock(&temp->lock);
    
            /*
            获得锁后访问temp->occupied 变量,此时如果车辆数为0 (occupied == 0)
            pthread_cond_wait 进行的操作就是忙等,释放锁(&temp->lock)供其他路线使用
            知道temp->car条件改变时再次将锁锁住
            */
            while(temp->occupied == 0)
            {
                pthread_cond_wait(&temp->car,&temp->lock);
            }
    
            temp->occupied--;
            temp->nextout++;
            temp->nextout %= temp->capacity;
            temp->cars_out++;
    
            pthread_cond_signal(&temp->space);
            pthread_mutex_unlock(&temp->lock);
        }
    
        return ((void *)NULL);
    }
    
    static void *monitor(void *carpark_in)
    {
        cp_t *temp;
        temp = (cp_t *)carpark_in;
    
        for(;;)
        {
            sleep(PERIOD);
    
            pthread_mutex_lock(&temp->lock);
    
            printf("Delta:%d
    ",temp->cars_in - temp->cars_out - temp->occupied);
            printf("Number of cars in carpark:%d
    ",temp->occupied);
    
            pthread_mutex_unlock(&temp->lock);
        }
    
        return ((void *)NULL);
    }
    
    int main(int argc,char **argv)
    {
        printf("main version 1.0
    ");
        if(argc != 2)
        {
            printf("Usage :%s carparksize
    ",argv[0]);
            exit(1);
        }
    
        cp_t outpark;
    
        initialise(&outpark,atoi(argv[1]));  //初始化停车场数据结构
    
        pthread_t car_in,car_out,m;                //定义线程变量
        pthread_t car_in2,car_out2;
    
        /***
        创建往停车场停车线程(生成者1)
        创建从停车场取车线程(消费者1)
        创建往停车场停车线程(生成者2)
        创建从停车场取车线程(消费者2)
        创建用于监控停车场状况的线程
        ***/
        pthread_create(&car_in,NULL,car_in_handler,(void*)&outpark);
        pthread_create(&car_out,NULL,car_out_handler,(void*)&outpark);
        pthread_create(&car_in2,NULL,car_in_handler,(void*)&outpark);
        pthread_create(&car_out2,NULL,car_out_handler,(void*)&outpark);
        pthread_create(&m,NULL,monitor,(void*)&outpark);
        
        //pthread_join的第二个参数为NULL,表示不关心线程返回状态,仅仅等待指定线程的终止
        pthread_join(car_in,NULL);
        pthread_join(car_out,NULL);
        pthread_join(car_in2,NULL);
        pthread_join(car_out2,NULL);
        pthread_join(m,NULL);
    
        return 0;
    }
  • 相关阅读:
    访客登录方案设计与应用
    VS Code下载
    dockerfile COPY命令失效
    mysql排序字段值相等时,分页数据重复
    go使用json包Marshal方法得到异常结果[123 125]
    Mysql知识点概览
    dockercompose安装
    docker安装
    Shell脚本执行报错:Syntax error: "(" unexpected
    二进制数的位运算,角色权限,多种账号来源
  • 原文地址:https://www.cnblogs.com/wanghao-boke/p/11613071.html
Copyright © 2011-2022 走看看