一. 实验目的

实现一个c程序,该程序能模拟解决有限缓冲问题,其中消费者和生产者产生和消耗随机数

二.实验内容

  1. 缓冲区

元数据类型为buffer_item,大小为1000的数组,按环形队列处理

  1. 生产者和消费者线程

生产者不断执行如下两个操作:消费一个随机数,生产两个随机数

消费者不断执行如下两个操作:生产一个随机数,消费两个随机数

3.Pthead线程创建

使用pthread_create创建5个生产者线程,5个消费者线程,主程序等待所有线程退出

三. 实验环境

Ubuntu Gnome 14.04

MinGW 4.8.1

Codeblocks 13.12

四.实验结果

基本采用semaphore实现了题目要求,其中

psem用于标示是否可生产(数量是否超过缓冲区大小),初始量为1000,每次消费+1,

csem用于标示是否可消费,初始量为0,每次生产+1,

sem用于标示是否可以修改缓冲区

但是以下情况会发生,导致程序死锁:

例如:5个消费者生产5个随机数,随后消耗这5个随机数,则生产者无法先消耗随机数再生产

五.附录

调试心得:
1.  有限缓冲问题确实可能死锁
2.  Pthread_create(tid,attr,func_name,arg)最后一个参数表示唯一传给线程的参数
3.  Void *func_name(void *arg)return需要用pthread_exit(),这个函数的作用是,终止调用它的线程并返回一个指向某个对象的指针,但是直接调用exit(0)会使整个进程退出. 如果主线程调用了pthread_exit,那么它退出了,子线程也不会退出。如果是return 0则会直接退出.
4.  使用函数pthread_exit退出线程,这是线程的主动行为;由于一个进程中的多个线程是共享数据段的,因此通常在线程退出之后,退出线程所占用的资源并不会随着线程的终止而得到释放,但是可以用pthread_join()函数来同步并释放资源。在Linux中,默认情况下是在一个线程被创建后,必须使用此函数对创建的线程进行资源回收,但是可以设置Threads attributes来设置当一个线程结束时,直接回收此线程所占用的系统资源
5.  在线程函数在编译时,需要连接库函数, -lpthread
 
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <cstdlib>
#include <cstring>
using namespace std;
typedef int item;
const int bsize = ;
const int pnum = ;
const int cnum = ;
const int looptimes = ;
sem_t sem,psem,csem; struct que{
item a[bsize];
int head,tail,n;
que(){
memset(a,,sizeof(a));
head=tail=n=;
}
}q; void p(char * str,int num){
while(num--){
sem_wait(&psem);
sem_wait(&sem);
q.a[q.head]=rand()%;
q.n++;
printf("%s: produce a[%d]:%d, now there is %d numbers in queue\n",str,q.head,q.a[q.head],q.n);
q.head=(q.head+)%bsize;
sem_post(&csem);
sem_post(&sem);
}
} void c(char *str,int num){
while(num--){
sem_wait(&csem);
sem_wait(&sem);
q.n--;
printf("%s: consume a[%d]:%d, now there is %d numbers in queue\n",str,q.tail,q.a[q.tail],q.n);
q.tail=(q.tail+)%bsize;
sem_post(&psem);
sem_post(&sem);
}
} void * producer(void * arg){
for(int i=;i<looptimes;i++){
c((char*)arg,);
p((char*)arg,);
}
pthread_exit();
}
void * consumer(void * arg){
for(int i=;i<looptimes;i++){
p((char*)arg,);
c((char*)arg,);
}
pthread_exit();
}
int main(){
sem_init(&sem,,);
sem_init(&psem,,);
sem_init(&csem,,);
char pname[][]={"p1","p2","p3","p4","p5"};
char cname[][]={"c1","c2","c3","c4","c5"};
pthread_t ptid[],ctid[];
pthread_attr_t pattr[],cattr[];
for(int i=;i<;i++){
pthread_attr_init(pattr+i);
pthread_create(ptid+i,pattr+i,producer,pname[i]);
pthread_attr_init(cattr+i);
pthread_create(ctid+i,cattr+i,consumer,cname[i]);
}
for(int i=;i<;i++){
pthread_join(ptid[i],NULL);
pthread_join(ctid[i],NULL);
}
puts("end");
return ;
}

Operating System Concepts 项目:生产者-消费者问题 线程的更多相关文章

  1. 生产者消费者模式-->线程

    #_author:来童星#date:2019/12/17#生产者消费者模式-->线程from queue import Queueimport random,time,threading#生产者 ...

  2. 8.12 day31 进程间通信 Queue队列使用 生产者消费者模型 线程理论 创建及对象属性方法 线程互斥锁 守护线程

    进程补充 进程通信 要想实现进程间通信,可以用管道或者队列 队列比管道更好用(队列自带管道和锁) 管道和队列的共同特点:数据只有一份,取完就没了 无法重复获取用一份数据 队列特点:先进先出 堆栈特点: ...

  3. python并发编程-进程间通信-Queue队列使用-生产者消费者模型-线程理论-创建及对象属性方法-线程互斥锁-守护线程-02

    目录 进程补充 进程通信前言 Queue队列的基本使用 通过Queue队列实现进程间通信(IPC机制) 生产者消费者模型 以做包子买包子为例实现当包子卖完了停止消费行为 线程 什么是线程 为什么要有线 ...

  4. Operating System Concepts with java 项目: Shell Unix 和历史特点

    线程间通信,fork(),waitpid(),signal,捕捉信号,用c执行shell命令,共享内存,mmap 实验要求: 1.简单shell: 通过c实现基本的命令行shell操作,实现两个函数, ...

  5. 生产者-消费者模型-线程安全队列Queue

    #python3 #product new data into the queue #comsume data from the queue from queue import Queue impor ...

  6. c++11 条件变量 生产者-消费者 并发线程

    http://baptiste-wicht.com/posts/2012/04/c11-concurrency-tutorial-advanced-locking-and-condition-vari ...

  7. Java多线程-同步:synchronized 和线程通信:生产者消费者模式

    大家伙周末愉快,小乐又来给大家献上技术大餐.上次是说到了Java多线程的创建和状态|乐字节,接下来,我们再来接着说Java多线程-同步:synchronized 和线程通信:生产者消费者模式. 一.同 ...

  8. 4、网络并发编程--僵尸进程、孤儿进程、守护进程、互斥锁、消息队列、IPC机制、生产者消费者模型、线程理论与实操

    昨日内容回顾 操作系统发展史 1.穿孔卡片 CPU利用率极低 2.联机批处理系统 CPU效率有所提升 3.脱机批处理系统 CPU效率极大提升(现代计算机雏形) 多道技术(单核CPU) 串行:多个任务依 ...

  9. Lucene.net站内搜索—4、搜索引擎第一版技术储备(简单介绍Log4Net、生产者消费者模式)

    目录 Lucene.net站内搜索—1.SEO优化 Lucene.net站内搜索—2.Lucene.Net简介和分词Lucene.net站内搜索—3.最简单搜索引擎代码Lucene.net站内搜索—4 ...

随机推荐

  1. [转载] linux 速查表

    原文: http://www.nixtutor.com/linux/all-the-best-linux-cheat-sheets/ 1. Linux Command Line Linux Refer ...

  2. js分组排序算法, OrderBy

    由于项目中需要对数据进行分组排序,类似于sql中 order by column1,column2....  实现的关键是 分组排序,第一个column1,排序完成之后,对其分组,然后按照column ...

  3. centos JDK安装

    第一步:查看Linux自带的JDK是否已安装 (卸载centOS已安装的1.4) 安装好的CentOS会自带OpenJdk,用命令 java -version ,会有下面的信息: java versi ...

  4. angularJS常见问题汇总

    问题描述 解决方案 当你简单的动态给页面插入html时, 此时html带有angular的语法不会执行的. var uploadInfo = '上传成功!<a ng-click="qu ...

  5. R语言实战

    教材目录 第一部分 入门 第一章 R语言介绍 第二章 创建数据集 第三章 图形初阶 第四章 基本数据管理 第五章 高级数据管理 第二部分 基本方法 第六章 基本图形 第七章 基本统计方法 第三部分 中 ...

  6. [转]Android各大网络请求库的比较及实战

    自己学习android也有一段时间了,在实际开发中,频繁的接触网络请求,而网络请求的方式很多,最常见的那么几个也就那么几个.本篇文章对常见的网络请求库进行一个总结. HttpUrlConnection ...

  7. VC++全局变量初始化

    目录 第1章说明    2 1.1 程序启动    2 1.2 强符号.弱符号    2 1.3 动态初始化顺序    3 1.4 exe调用dll    4 1.5 禁用动态初始化    4 1.6 ...

  8. 为什么在非UI线程中操作UI的改变失不安全的

    因为你如果允许在非UI线程更新操作UI的东西,那我再另一个非UI线程也可以更新这个Ui的东西 这样就会有冲突,比如你的线程刚好跑到修改UI这里,我的另一个UI也有可能跑到这里,所以这样导致线程不安全. ...

  9. ios开发中的toll-free bridged

    所谓的Toll-free bridging是说您可以在某个框架的方法或函数 同时使用Core Foundatio和Foundation 框架中的某些类型. 很多数据类型支持这一特性,其中包括群体和字符 ...

  10. jquery和js使用技巧

    1. 如何得知图片已加载完毕 这也一个没有很好文档说明的问题(至少在我查找时没看到),但是在创建照片库.旋转灯笼效果等方面,它是相当常见的需求.而这在jQuery中很容易实现. 所有你要做的就是在IM ...