多线程编程

来源:互联网 发布:深入浅出 python 中文 编辑:程序博客网 时间:2024/04/30 08:27

        找工作的日子渐渐临近了,想来好好复习下之前学的c/c++,不复习还不知道,一复习吓一跳,忘记了太多的东西,没办法,再次学习呗,以前都没有做记录,现在每次复习都来做个笔记,以便以后能够更快的浏览。话不多说,是多线程问题,还是以具体的列子来记录最实在:虽然我很渣渣,希望大家指出不足之处。。。

  问题来源<<多线程生产者消费者模型仿真停车场>>,学软件的都应该学过操作系统原理,与书上面的列题类似,用到知识有:什么是线程,线程的创建,获取线程号,互斥信号量,等。

         问题假设:有一停车场,有两进两出,同时可随时查看车场的车辆数目等;

故根据问问题得出,由于共用的是一个停车场上的资源,故需创建5个级线程,而不是进程。贴出关键部分代码与注释如下:

//《多线程生产者消费者模型仿真停车场》//实现一个基于生产者消费者模型的的停车场停车信息系统,//还可以深入理解多线程的创建终止和同步过程,//以及线程互斥访问共享数据的锁机制原理。//生产者消费者模型的概念//互斥量的使用,锁机制的实现方式//本项目的完整代码如下:#include <pthread.h>#include <stdlib.h>#include <unistd.h>#include <stdio.h>#define ONE_SECOND 1000000#define RANGE 10#define PERIOD 2#define NUM_THREADS 4 // 定义数据结构描述停车场信息typedef struct {    int *carpark; // 用一个整数数组 buffer 模拟停车场停车位    int capacity; // 停车场的车辆容量    int occupied; // 停车场现有车辆数目    int nextin;  // 下一个进来的车的停车位置(用 carpark 数组代表的下标表示)    int nextout; // 下一个取走的车的停车位置(用 carpark 数组代表的下标表示)    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 * car_in_handler(void *cp_in);static void * car_out_handler(void *cp_in);static void * monitor(void *cp_in);static void initialise(cp_t *cp, int size);int main(int argc, char *argv[]) {    if (argc != 2) {        printf("Usage: %s carparksize\n", argv[0]);        exit(1);    }    cp_t ourpark;    initialise(&ourpark, atoi(argv[1])); // 初始化停车场数据结构    pthread_t car_in, car_out, m;  // 定义线程变量    pthread_t car_in2, car_out2;    pthread_create(&car_in, NULL, car_in_handler, (void *)&ourpark);  // 创建往停车场停车线程(生产者1)    pthread_create(&car_out, NULL, car_out_handler, (void *)&ourpark); // 创建从停车场取车线程(消费者1)    pthread_create(&car_in2, NULL, car_in_handler, (void *)&ourpark); // 创建往停车场停车线程(生产者2)    pthread_create(&car_out2, NULL, car_out_handler, (void *)&ourpark); // 创建从停车场取车线程(消费者2)    pthread_create(&m, NULL, monitor, (void *)&ourpark);  // 创建用于监控停车场状况的线程    // 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);    exit(0);}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--; // 现有车辆数目减1        temp->nextout++;        temp->nextout %= temp->capacity;        temp->cars_out++;        // 可能有的人在等有空空车位(线程),这是发送 temp->space 条件变量        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);        /* 证明锁机制保证线程实现的生产者消费者模型正确的方式是:        temp->cars_in - temp->cars_out - temp->occupied == 0,即总的进来的车 ==         总的开出去的车 + 停车场现有的车 */        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);}


       

0 0
原创粉丝点击