一. 实验目的

实现一个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. JS 字符串编码函数(解决URL特殊字符传递问题):escape()、encodeURI()、encodeURIComponent()区别详解

    javaScript中有三个可以对字符串编码的函数,分别是: escape,encodeURI,encodeURIComponent,相应3个解码函数:unescape,decodeURI,decod ...

  2. 手机CPU知识扫盲:谈谈手机CPU架构与原理 (全

    CPU是手机上面最复杂,最贵的Soc(芯片),担任的也是手机中大脑的位 置,是手机跑分性能的决定性硬件.智能手机发展到今天,各大手机CPU厂商也从春秋战国逐渐到了现在四国鼎立的时代(高通,MTK,三星 ...

  3. MySQL忘记root密码--skip-grant-tables

    使用--skip-grant-tables选项启动MYSQL时,服务器将不加载权限判断,这样就可以进行授权和密码更新操作了,具体步骤如下: 1. 停止mysql /etc/init.d/mysqld ...

  4. html5 和css3的小知识!

    阿里web字体的使用 (1)进入官网  点击webfont (2)输入对应的文字 然后选择添加字体 (3)可以直接引用线上地址或者本地下载,引用线上地址需要添加http,(在服务器环境下可以不用),如 ...

  5. Android 面试题总结

    Android 面试题总结(不断更新) 1.INETNT几种有关Activit的启动方式FLAG_ACTIVITY_BROUGHT_TO_FRONT 将ACTIVITY带到最前面FLAG_ACTIVI ...

  6. Maven打包遇到的一些问题(zhuan)

    http://qqbwww.iteye.com/blog/2042307 **************************************** #Maven打包遇到的一些问题 ## 1.将 ...

  7. OpenGL的GLUT注册回调函数[转]

    OpenGL的注册回调函数 void glutDisplayFunc(void (*func)(void) ); 为当前窗口设置显示回调函数 void glutOverlayDisplayFunc(v ...

  8. SwitchCompat 修改颜色

    Ok, so I'm sorry but most of these answers are incomplete or have some minor bug in them. The very c ...

  9. 简单的css居中问题(日常记录)

    1.今天遇到了一个奇怪的问题:因为网页要适配大小分辨屏幕,需要把一张图片放到div中,我的初始思路是把图放在div中绝对对位给top50%left50%,但是不行,因为当网页调窄时图片就因为显得太大了 ...

  10. WinForm应用程序之注册模块的设计与实现

    Posted on 2012-11-13 10:21 星星之火116 阅读(3260) 评论(4) 编辑 收藏 我们在安装一些桌面应用程序的时候,往往在会有提示当前用户使用的是试用版,要进行注册.刚好 ...