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\n",temp->cars_in - temp->cars_out - temp->occupied);
        printf("Number of cars in carpark:%d\n",temp->occupied);

        pthread_mutex_unlock(&temp->lock);
    }

    return ((void *)NULL);
}

int main(int argc,char **argv)
{
    printf("main version 1.0\n");
    if(argc != 2)
    {
        printf("Usage :%s carparksize\n",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;
}

原文地址:https://www.cnblogs.com/wanghao-boke/p/11613071.html

时间: 2024-08-06 15:32:00

Linux下多线程模拟停车场停车的相关文章

linux下多线程下载工具axel的编译安装

axel 是Linux 命令行下多线程的下载工具,支持断点续传,速度通常情况下是Wget的几倍 官方主页:http://axel.alioth.debian.org/ 源码下载: #curl -O http://pkgs.fedoraproject.org/repo/pkgs/axel/axel2.4.tar.gz/a2a762fce0c96781965c8f9786a3d09d/axel-2.4.tar.gz 编译安装: # tar -xvf axel-2.4.tar.gz  && cd

linux下多线程编程

最近研究mysql源码,各种锁,各种互斥,好在我去年认真学了<unix环境高级编程>, 虽然已经忘得差不多了,但是学过始终是学过,拿起来也快.写这篇文章的目的就是总结linux 下多线程编程,作为日后的参考资料. 本文将介绍linux系统下多线程编程中,线程同步的各种方法.包括: 互斥量(mutex) 读写锁 条件变量 信号量 文件互斥 在介绍不同的线程同步的方法之前,先简单的介绍一下进程和线程的概念, 它们的优缺点,线程相关的API,读者——写者问题和哲学家就餐问题. 基础知识 1. 进程和

linux下多线程的调试

多线程调试的基本命令(均在gdb命令行使用): info threads ---- 显示当前可调试的所有线程.每一个线程都有自己的线程ID,显示结果中前面有*的表示当前调试的线程. eg: (gdb)info threads ID    Target ID 3     Thread 0x------(LWP 1235) 2    Thread 0x------(LWP 1234) *1    Thread 0x------(LWP 1233)    //当前活动的线程 最前面的数字1.2.3表示

Linux下多线程下载工具 - Axel

Axel 是 Linux 下一个不错的HTTP/FTP高速下载工具.支持多线程下载.断点续传,且可以从多个地址或者从一个地址的多个连接来下载同一个文件.适合网速不给力时多线程下载提高下载速度.比如在国内VPS或服务器上下载lnmp一键安装包用Axel就比wget快. CentOS安装Axel: 目前yum源上没有Axel,我们可以到http://pkgs.repoforge.org/axel/下载rpm包安装. 32位CentOS执行下面命令: wget -c http://pkgs.repof

linux下多线程断点下载工具-alex

今天要下载一下14G左右的文件,用wget约10小时,后来发现linux下有个多线程支持断点续传的下载工具alex,试了一下,下载速度大大增加. 包地址:http://pkgs.repoforge.org/axel/ 安装 下载rpm文件并安装: $ wget http://pkgs.repoforge.org/axel/axel-2.4-1.el6.rf.x86_64.rpm $ rpm -i axel-2.4-1.el6.rf.x86_64.rpm 主要参数 -n x:启动x个线程下载 -s

Linux下多线程下载工具MWget和Axel使用介绍

linux运维在操作linux过程中,用得最多的linux下载工具想必一定是wget,没有看到哪一台服务器没装过wget的,或许有人使用ftp下载,也有人使用多线程的axel以及ProZilla,毫无疑问这两个工具都非常的出色,但是对于习惯使用wget的人来说显得不适应,于是老外便开发了多线程版本的wget工具mwget,m表示multi多线程的意思. mwget官方地址:http://sourceforge.net/projects/kmphpfm/?source=dlp # cd /usr/

Linux下多线程查看工具(pstree、ps、pstack),linux命令之-pstree使用说明, linux 查看线程状态。 不指定

0.最常用 pstree:[[email protected] temp]# pstree -a|grep multe  |       |   `-multepoolser  |       |       `-multepoolser  |       |           `-2*[{multepoolser}] 1. > top 可以显示所有系统进程 按u, 再输入相应的执行用户名称,比如Tom 可以看到Tom用户启动的所有进程和对应的pid 2. > pstack pid 可以看到

Linux下多线程2——多线程的优点

使用多线程的理由1: 使用多线程的理由之一是和进程相比,它是一种非常"节俭"的多任务操作方式.我们知道,在 Linux 系统下,启动一个新的进程必须分配给它独立的地址空 间,建立众多的数据表来维护它的代码段.堆栈段和数据段,这是一种"昂贵"的多任务工作方式.而运行于一个进程中的多个线程,它们彼此之间使用相同的地址 空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,而且,线程间彼此切换所需的时间也远远小于进程间切换所需要的时间.使用多线程

为什么linux下多线程程序如此消耗虚拟内存【转】

转自:http://blog.csdn.net/chen19870707/article/details/43202679 权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 探索 灵光一现 刨根问底 意外发现 Author:Echo Chen(陈斌) Email:[email protected] Blog:Blog.csdn.net/chen19870707 Date:Jan.27th, 2015 最近游戏已上线运营,进行服务器内存优化,发现一个非常奇妙的问题,我们的认证服