多线程编程
来源:互联网 发布:深入浅出 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
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- android沉浸式状态栏
- 图片加载框架-Fresco
- Java解码网站post字符串(swich case用法和乱码判断)
- android-----UI布局之TabHost与TextView
- Abstraction and Structure——《Learning Python》抽象之函数
- 多线程编程
- 过滤器知识总结
- Android学习笔记(九):按钮添加点击事件的4种方式
- apache启动脚本
- android(SignalA)接收.net(SignalR)推送过来的消息
- JavaWeb多种乱码解决方法
- css:display的属性选择
- swap关于指针的使用
- linux常用20命令。