#include <stdio.h>  

#include <pthread.h>  

#define BUFFER_SIZE 16 // 缓冲区数量  

    struct prodcons  

    {  

        // 缓冲区相关数据结构  

        int buffer[BUFFER_SIZE]; /* 实际数据存放的数组*/  

        pthread_mutex_t lock; /* 相互排斥体lock 用于对缓冲区的相互排斥操作 */  

        int readpos, writepos; /* 读写指针*/  

        pthread_cond_t notempty; /* 缓冲区非空的条件变量 */  

        pthread_cond_t notfull; /* 缓冲区未满的条件变量 */  

    };  

    /* 初始化缓冲区结构 */  

    void init(struct prodcons *b)  

    {  

        pthread_mutex_init(&b->lock, NULL);  

        pthread_cond_init(&b->notempty, NULL);  

        pthread_cond_init(&b->notfull, NULL);  

        b->readpos = 0;  

        b->writepos = 0;  

    }  

    /* 将产品放入缓冲区,这里是存入一个整数*/  

    void put(struct prodcons *b, int data)  

    {  

        pthread_mutex_lock(&b->lock);  

        /* 等待缓冲区未满*/  

        if ((b->writepos + 1) % BUFFER_SIZE == b->readpos)  

        {  

            pthread_cond_wait(&b->notfull, &b->lock);  

        }  

        /* 写数据,并移动指针 */  

        b->buffer[b->writepos] = data;  

        b->writepos++;  

        if (b->writepos >= BUFFER_SIZE)  

            b->writepos = 0;  

        /* 设置缓冲区非空的条件变量*/  

        pthread_cond_signal(&b->notempty);  

        pthread_mutex_unlock(&b->lock);  

    }   

    /* 从缓冲区中取出整数*/  

    int get(struct prodcons *b)  

    {  

        int data;  

        pthread_mutex_lock(&b->lock);  

        /* 等待缓冲区非空*/  

        if (b->writepos == b->readpos)  

        {  

            pthread_cond_wait(&b->notempty, &b->lock);  

        }  

        /* 读数据,移动读指针*/  

        data = b->buffer[b->readpos];  

        b->readpos++;  

        if (b->readpos >= BUFFER_SIZE)  

            b->readpos = 0;  

        /* 设置缓冲区未满的条件变量*/  

        pthread_cond_signal(&b->notfull);  

        pthread_mutex_unlock(&b->lock);  

        return data;  

    }  

      

      

    /* 測试:生产者线程将1 到10000 的整数送入缓冲区,消费者线

       程从缓冲区中获取整数,两者都信息打印*/  

    #define OVER ( - 1)  

    struct prodcons buffer;  

    void *producer(void *data)  

    {  

        int n;  

        for (n = 0; n < 50; n++)  

        {  

            printf("%d ---producer==>\n", n);  

            put(&buffer, n);  

        } put(&buffer, OVER);  

        return NULL;  

    }  

      

      

    void *consumer(void *data)  

    {  

        int d;  

        while (1)  

        {  

            d = get(&buffer);  

            if (d == OVER)  

                break;  

            printf("---consumer==>%d \n", d);  

        }  

        return NULL;  

    }  

      

      

    int main(void)  

    {  

        pthread_t th_a, th_b;  

        void *retval;  

        init(&buffer);  

        /* 创建生产者和消费者线程*/  

        pthread_create(&th_a, NULL, producer, 0);  

        pthread_create(&th_b, NULL, consumer, 0);  

        /* 等待两个线程结束*/  

        pthread_join(th_a, &retval);  

        pthread_join(th_b, &retval);  

        return 0;  

    }

一个经典的消费者和生产者的实现(linux )的更多相关文章

  1. Linux 进程间通信(包含一个经典的生产者消费者实例代码)

    前言:编写多进程程序时,有时不可避免的需要在多个进程之间传递数据,我们知道,进程的用户的地址空间是独立,父进程中对数据的修改并不会反映到子进程中,但内核是共享的,大多数进程间通信方式都是在内核中建立一 ...

  2. Java程序设计之消费者和生产者

    新建一个Break类,表示食物数量. public class Break { public static final int MAX = 10; //最多一次性煮十个面包 Stack<Inte ...

  3. java多线程-消费者和生产者模式

    /* * 多线程-消费者和生产者模式 * 在实现消费者生产者模式的时候必须要具备两个前提,一是,必须访问的是一个共享资源,二是必须要有线程锁,且锁的是同一个对象 * */ /*资源类中定义了name( ...

  4. Java多线程消费者、生产者的基本思路

    多线程主要考察的就是 线程的同步控制   生产者消费者的思路就是,当 一个线程执行时让另一个线程 挂起就行了 ThreadOne.ThreadTwo同时运行,添加一个变量在一个公共类(下边的Funct ...

  5. python_并发编程——消费者和生产者模型

    消费者和生产者模型 from multiprocessing import Process,Queue import time import random class Producer(Process ...

  6. springcloud 实现简单的 消费者和生产者 模式(Restfule 的风格)

    一.springcloud 实现简单的 消费者和生产者 模式(Restfule 的风格) 1.实现简单的消费者和生产者 springcloud使用的http协议进行传输数据,也就是说springclo ...

  7. [一个经典的多线程同步问题]解决方案一:关键段CS

    前面提出了一个经典的多线程同步互斥问题,本篇将用关键段CRITICAL_SECTION来尝试解决这个问题. 本文先介绍如何使用关键段,然后再深层次的分析下关键段的实现机制和原理. 关键段CRITICA ...

  8. 用Python设计一个经典小游戏

    这是关于Python的第9篇文章,介绍如何用Python设计一个经典小游戏:猜大小. 在这个游戏中,将用到前面我介绍过的所有内容:变量的使用.参数传递.函数设计.条件控制和循环等,做个整体的总结和复习 ...

  9. 原来这是一个经典面试题-------Day61

    前几天在table的操作中,记录了动态生成表格的三种方式: 1.html语言的拼接:用字符串或者数组拼接在html语言中,这个理解起来最直观 2.插入行和列:insertRow()和insertCel ...

随机推荐

  1. Java对象简单实用(计算器案例)

    对 Java中的对象与属性,方法的使用,简单写了个案例 import java.util.Scanner; class Calculste { int a; //定义两个整数 int b; Strin ...

  2. php-5.3源码编译autoconf版本不符合解法

    1. 网上下载符合版本的autoconf 2. 卸载本地原本的autoconf 3. 解压autoconf 后进入目录 ./configure && make && s ...

  3. Android开发笔记(3)——GridLayout

    笔记链接:http://www.cnblogs.com/igoslly/p/6799939.html GirdLayout 计算器实例及详尽的笔记:http://www.cnblogs.com/sky ...

  4. C++(存储类)经典!!

    C++变量的存储类别(动态存储.静态存储.自动变量.寄存器变量.外部变量)动态存储方式与静态存储方式 我们已经了解了变量的作用域.作用域是从空间的角度来分析的,分为全局变量和局部变量. 变量还有另一种 ...

  5. ElasticSearch 安装使用

    安装: 1.下载ElasticSearch.解压到相关文件夹 2.运行elasticsearch.bat,启动程序 3.在浏览器输入:http://localhost:9200/,显示相关Es内容即安 ...

  6. 浮动布局demo

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  7. Java编辑编译及运行环境

    Java编辑编译及运行环境 Microsoft Windows 编辑工具 EditPlus JDK JDK(Java Development Kit,Java开发工具包)安装JDK之后,其中bin文件 ...

  8. JavaScript中的方法

    JavaScript中的方法 在JavaScript中,可以通过对象来调用对应的方法.在JavaScript中,有三个重要的window对象方法:用于显示警告信息的alert.用于显示确认信息的con ...

  9. 19异常和file部分笔记

    19异常和file部分笔记-2018/09/041.异常  1.1 throwable()几个常见方法 * getMessage()获取异常信息,返回字符串 * toString()获取异常类名和异常 ...

  10. Codeforces 280C - Game on Tree

    传送门:280C - Game on Tree 不知道期望是啥的请自行Baidu或Google,(溜了 题目大意,有一棵有根树,每次随机选择一个节点,将这个节点和它的子树删除,问将整棵树删除的期望次数 ...