惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

MyScale Blog
MyScale Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
阮一峰的网络日志
阮一峰的网络日志
罗磊的独立博客
博客园 - 叶小钗
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
美团技术团队
酷 壳 – CoolShell
酷 壳 – CoolShell
雷峰网
雷峰网
宝玉的分享
宝玉的分享
大猫的无限游戏
大猫的无限游戏
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Last Week in AI
Last Week in AI
爱范儿
爱范儿
小众软件
小众软件
K
Kaspersky official blog
P
Proofpoint News Feed
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - Franky
V
Vulnerabilities – Threatpost
博客园_首页
Microsoft Security Blog
Microsoft Security Blog
C
Cybersecurity and Infrastructure Security Agency CISA
V
V2EX
C
Check Point Blog
S
Schneier on Security
P
Palo Alto Networks Blog
IT之家
IT之家
GbyAI
GbyAI
T
Threat Research - Cisco Blogs
Hugging Face - Blog
Hugging Face - Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Apple Machine Learning Research
Apple Machine Learning Research
C
Cyber Attacks, Cyber Crime and Cyber Security
T
Tailwind CSS Blog
Project Zero
Project Zero
Y
Y Combinator Blog
V
Visual Studio Blog
Simon Willison's Weblog
Simon Willison's Weblog
T
Threatpost
Scott Helme
Scott Helme
L
LINUX DO - 热门话题
S
Securelist
C
CERT Recently Published Vulnerability Notes
A
Arctic Wolf
M
MIT News - Artificial intelligence
人人都是产品经理
人人都是产品经理

博客园 - 刘寅

一起来用Websocket(二):Websocket协议详细分析 一起来用Websocket-目录 一起来用Websocket(一)开篇 Websocket!Socket在HTML5复活 封闭式开发小记(11):封闭式开发的测试发布(制定版本规则,展现开发进度) 封闭式开发小记(10):封闭式开发的项目汇报(区分汇报类别和听众、争取最大认可) 封闭式开发小记(9):封闭式开发的最后一天(开发中的一些心情记录,和开发无关) 封闭式开发小记(8):封闭式开发的项目讨论 封闭式开发小记(7):如何和谐沟通、提高士气(结合开发实际冲突来深入讨论合作与沟通) 封闭式开发小记(6):封闭式开发的文档管理 封闭式开发小记(5):封闭式开发的敏捷开发 封闭式开发小记(4):封闭式开发的架构设计 封闭式开发小记(3):封闭式开发的人员配备 封闭式开发小记(1):封闭式开发的基本装备 封闭式开发小记(2):封闭式开发的时间安排 进程机制与并发程序设计-Linux下C实现-源码-makefile .NET 的 代码整洁之道 与 测试驱动开发 系列之(一)CleanCode 第14章 进程机制与并发程序设计-Linux下C实现(一) 睡觉的理发师问题 操作系统常用页面置换算法模拟实验下载 07 zsb C练习上机(二)
进程机制与并发程序设计-Linux下C实现(二) 生产者与消费者问题
刘寅 · 2008-01-06 · via 博客园 - 刘寅

          进程机制与并发程序设计-Linux下C实现(二) 生产者与消费者问题
                                                                       作者:刘寅 08-01-06

一,问题分析:

在学习进程互斥中,有个著名的问题:生产者-消费者问题。这个问题是一个标准的、著名的同时性编程问题的集合:一个有限缓冲区和两类线程,它们是生产者和消费者,生产者把产品放入缓冲区,相反消费者便是从缓冲区中拿走产品。生产者在缓冲区满时必须等待,直到缓冲区有空间才继续生产。消费者在缓冲区空时必须等待,直到缓冲区中有产品才能继续读取。在这个问题上主要考虑的是:缓冲区满或缓冲区空以及竞争条件(race condition)

二,伪码分析:


empty为缓冲区中空元素的个数,初值为n

flul为缓冲区中已生产元素的个数,初值为0

Mutex为对缓冲区互斥访问加的锁

Main()

{

codebegin

     Productor();

     Customer();
codeend

}

Productor() while(true)

{    

    P(empty)
p(mutex)

生产产品

Buffer [i]中放产
V(mutex)

    V(full)

}

Customer()

    While(true)

    {

P(full)

P(mutex)

       Buffer[J]取产品

V(mutex)

V(empty)

消费产品

}


三,linux下实现:

linux readhat 9.0下测试通过

进入pro_cus 文件夹,然后用shell运行”make ”命令即可

Pro_cus文件说明

   --const.h  在本项目中使用到的一些常量的定义

 1#ifndef CONST_H
 2#define CONST_H
 3#define MaxSize 10 //栈中最多只有十个元素 
 4#define TRUE 1
 5#define FALSE 0
 6#define ERROR 0
 7#define OVERFLOW -2
 8#define OK 1
 9#define MAXSIZE 20
10#define MAXLEN 100//字符串的最大长度
11#endif 
12
13


       --exp1.c  本项目的主程序

 1#include <stdio.h>
 2#include <stdlib.h>
 3#include <unistd.h>
 4#include <pthread.h>
 5#include <errno.h>
 6#include <sys/ipc.h>
 7#include <semaphore.h>
 8#include <fcntl.h>
 9#include "Queue.h"
10#include "const.h"
11#define N 5
12time_t end_time;
13sem_t mutex,full,empty;
14int fd;
15Queue * qt; /*缓冲区*/
16Elemtype p;
17
18void consumer(void *arg);
19void productor(void *arg);
20
21int main(int argc, char *argv[])
22{
23    pthread_t id1,id2;
24    pthread_t mon_th_id;
25    int ret;
26    end_time = time(NULL)+30;
27  qt = InitQueue();
28  p.lNumber = 1000;
29    ret=sem_init(&mutex,0,1);        /*初使化互斥信号量为1*/
30    ret=sem_init(&empty,0,N);        /*初使化empty信号量为N*/
31    ret=sem_init(&full,0,0);        /*初使化full信号量为0*/
32    if(ret!=0)
33    {
34        perror("sem_init");
35    }

36    ret=pthread_create(&id1,NULL,(void *)productor, NULL);        /*创建两个线程*/
37    if(ret!=0)
38        perror("pthread cread1");
39    ret=pthread_create(&id2,NULL,(void *)consumer, NULL);
40    if(ret!=0)
41        perror("pthread cread2");
42    pthread_join(id1,NULL);
43    pthread_join(id2,NULL);
44
45    exit(0);
46}

47/*生产者线程*/
48void productor(void *arg)
49{
50    int i,nwrite;
51    while(time(NULL) < end_time){
52        sem_wait(&empty);// p(empty)
53        sem_wait(&mutex);// p(mutex)
54        if(TRUE==QueueFull(*qt))
55        {
56                //队满
57                printf("Productor:buffer is full ,please try to write  later.\n");
58        }

59        else
60        {
61                EnQueue(qt,p);
62                printf("Productor:write [%d] to buffer \n",p.lNumber);
63                p.lNumber++;
64        }

65        
66        sem_post(&full);//v(full)
67        sem_post(&mutex);//v(mutex)
68        sleep(1);
69    }

70}
//productor
71
72/*消费者线程*/
73void consumer(void *arg)
74{
75    int nolock=0;
76    int ret,nread;
77    Elemtype p2;
78    while((time(NULL) < end_time)||(FALSE==(QueueEmpty(*qt))))
79    {
80        sem_wait(&full);//p(full)
81        sem_wait(&mutex);//p(mutex)
82        if(TRUE==QueueEmpty(*qt))
83            {    
84                //队空
85                printf("Consumer:the buffer is empty,please try to read later.\n");
86            }

87            else
88            {
89                     DeQueue(qt,&p2);
90                     printf("Consumer:read [%d] from buffer.\n",p2.lNumber);
91            }

92        sem_post(&empty);//v(empty)
93        sem_post(&mutex);//v(mutex)
94        sleep(2);
95    }
/*end of     while((time(NULL) < end_time)||(FALSE==(QueueEmpty(*qt))))*/
96}
//consumer
97
98

       --Queue.c 循环队列的实现

 1/*
 2队列的基本操作函数
 3*/

 4#include "stdio.h"
 5#include "malloc.h"
 6#include "const.h"
 7#include "Queue.h"
 8/*
 9 初使化队列
10*/

11Queue * InitQueue()
12{
13    Queue * Q = (Queue *)malloc(sizeof(Queue));
14
15    Q->front = Q->rear = 0;
16    return Q;
17}

18
19/*
20    进队
21*/

22int EnQueue(Queue *Q,Elemtype x)
23{
24    if((Q->rear + 1)%MaxSize==Q->front)/* 队满 */
25        return FALSE;
26    else
27    {
28        Q->q[Q->rear] = x;
29        Q->rear = (Q->rear+1)%MaxSize;
30        return TRUE;
31    }

32}

33
34/*
35    出队
36*/

37int DeQueue(Queue *Q,Elemtype *x)
38{
39    if(Q->rear==Q->front)/*队空*/
40        return FALSE;
41    else
42    {
43        *= Q->q[Q->front];
44        Q->front = (Q->front+1)%MaxSize;
45        return TRUE;
46    }

47}

48
49/*
50    判断队是否为空,空返回0
51    非空返回 1
52*/

53int QueueEmpty(Queue Q)
54{
55    if(Q.rear==Q.front)/*队空*/
56        return TRUE;
57    else
58        return FALSE;
59}

60
61/*
62    返回队例中的最后的一个元素(原队列还要存在)
63*/

64Elemtype Last(Queue *Q)
65{
66  
67    Elemtype *prElem = NULL;
68    Queue *prTempQueue;
69    /*这个临时队列,把原队列放到里面,当取完最后一
70    个元素后,就把这个队列中的元素放回原来的队列*/

71    prTempQueue = InitQueue();
72    while(QueueEmpty(*Q)==1)
73    {
74        DeQueue(Q,prElem);
75        EnQueue(prTempQueue,*prElem);
76    }

77    while(QueueEmpty(*prTempQueue)==1)
78    {
79        DeQueue(prTempQueue,prElem);
80        EnQueue(Q,*prElem);
81    }

82    return *prElem;
83}
/*Last*/
84
85/*
86    判断队是否为满,满返回TRUE
87    非满返回FALSE
88*/

89int QueueFull(Queue Q)
90{
91    if(((Q.rear+1)%MaxSize)==Q.front)/*队空*/
92        return TRUE;
93    else
94        return FALSE;
95}

96

       --Queue.h 循环队列的函数说明

 1#ifndef QUEUE_H_LY
 2#define QUEUE_H_LY
 3#include "Typedefine.h"
 4/*
 52007-12-23 10:31:14
 6*/

 7/*
 8    初使化队列信息
 9*/

10Queue * InitQueue();
11/*
12    进队(因为没有队满的情况,所以没有返回值)
13*/

14
15int EnQueue(Queue *Q,Elemtype x);
16/*
17    出队,x为出队的那个结点的数据域
18    返回:1成功/0失败
19*/

20int DeQueue(Queue *Q,Elemtype *x);
21/*
22    判断队空1(不空)/0(为空)
23*/

24int QueueEmpty(Queue Q);
25/*
26    统计一个栈链中的元素的个数
27*/

28int QueueCount(Queue *HQ);
29
30/*
31    判断队是否为满,满返回TRUE
32    非满返回FALSE
33*/

34int QueueFull(Queue Q);
35
36#endif   
37

       --Typedefine.h 本项目中用到一些数据结构,详细的请参考代码

Code


 源码下载