LINUX学习:生产者&消费者模型复习

回顾一下生产者消费者模型。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <semaphore.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#define ERR_EXIT(m)     do {         perror(m);        exit(EXIT_FAILURE);    }while(0)
#define CONSUMERS_COUNT 1
#define PRODUCERS_COUNT 2
#define BUFFSIZE 10

int g_buffer[BUFFSIZE];

unsigned short in = 0;
unsigned short out = 0;
unsigned short product_id = 0;
unsigned short consume_id = 0;

sem_t g_sen_full;
sem_t g_sen_empty;
pthread_mutex_t g_mutex;

pthread_t g_thread[CONSUMERS_COUNT+PRODUCERS_COUNT];

void* consume(void* arg)
{
    int i;
    while(1)
    {
        sem_wait(&g_sen_empty);
        pthread_mutex_lock(&g_mutex);
        for (i = 0; i < BUFFSIZE; ++i)
        {
            /* code */
            printf("%02d\n", i);
            if(g_buffer[i] == -1)
                printf("%s", "null");
            else
                printf("%d\n", g_buffer[i]);
            if(i == out)
                printf("\t<--consume\n");
            printf("\n");
        }
        consume_id = g_buffer[out];
        printf("begin consume product %d\n", consume_id);
        g_buffer[out] = -1;
        out = (out + 1) % BUFFSIZE;
        pthread_mutex_unlock(&g_mutex);
        sem_post(&g_sen_full);
        sleep(1);
    }
    return NULL;
}
void* produce(void *arg)
{
    int num = (int)arg;
    int i;
    while(1)
    {
        printf("%d waiting buffer_full\n", num);
        sem_wait(&g_sen_full);
        pthread_mutex_lock(&g_mutex);
        for (i = 0; i < BUFFSIZE; ++i)
        {
            /* code */
            printf("%02d\n", i);
            if(g_buffer[i] == -1)
                printf("%s", "null");
            else
                printf("%d\n", g_buffer[i]);
            if(i == in)
                printf("\t<--produce\n");
            printf("\n");
        }
        printf("begin produce product %d\n", product_id);
        g_buffer[in] = product_id;
        in = (in +1) % BUFFSIZE;
        printf("end produce product %d\n", product_id++);
        pthread_mutex_unlock(&g_mutex);
        sem_post(&g_sen_empty);
    }
    return NULL;
}
int main(int argc, const char *argv[])
{
    int i;
    for (i = 0; i < BUFFSIZE; ++i)
    {
        /* code */
        g_buffer[i] = -1;
    }
    // 初始化信号量
    sem_init(&g_sen_full, 0, BUFFSIZE);
    sem_init(&g_sen_empty, 0, 0);
    // 初始化锁
    pthread_mutex_init(&g_mutex, NULL);

    for (i = 0; i < CONSUMERS_COUNT; ++i)
    {
        /* code */
        pthread_create(&g_thread[i], NULL, consume, (void*)i);
    }
        for (i = 0; i < PRODUCERS_COUNT; ++i)
    {
        /* code */
        pthread_create(&g_thread[CONSUMERS_COUNT+i], NULL, produce, (void*)i);
    }
        for (i = 0; i < CONSUMERS_COUNT+PRODUCERS_COUNT; ++i)
    {
        /* code */
        pthread_join(g_thread[i], NULL);
    }

    sem_destroy(&g_sen_empty);

    sem_destroy(&g_sen_full);
    pthread_mutex_destroy(&g_mutex);
    return 0;
}

东莞东方

 

再写一个 条件变量的版本。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <semaphore.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#define ERR_EXIT(m)     do {         perror(m);        exit(EXIT_FAILURE);    }while(0)
#define CONSUMERS_COUNT 2
#define PRODUCERS_COUNT 1
#define BUFFSIZE 10

unsigned short in = 0;
unsigned short out = 0;
unsigned short product_id = 0;
unsigned short consume_id = 0;

sem_t g_sen_full;
sem_t g_sen_empty;
pthread_mutex_t g_mutex;
pthread_cond_t g_cond;
pthread_t g_thread[CONSUMERS_COUNT+PRODUCERS_COUNT];

int nready = 0;

void* consume(void* arg)
{
    int num = (int)arg;
    while(1)
    {
        pthread_mutex_lock(&g_mutex);
        while(nready==0)
        {
            printf("begin wait a condtion\n");
             pthread_cond_wait(&g_cond, &g_mutex);
        }

        printf("no.%dend of wait a condtion ....\n", num);
        --nready;
        printf("消费者%d消耗一个产品\n", num);
        pthread_mutex_unlock(&g_mutex);

    }
    return NULL;
}
void* produce(void *arg)
{
    int num = (int)arg;
    while(1)
    {
        pthread_mutex_lock(&g_mutex);
        ++nready;
        printf("生产者%d生产了一个产品并发送signal..\n", num);
        pthread_cond_signal(&g_cond);
        pthread_mutex_unlock(&g_mutex);
        sleep(5);
    }
    return NULL;
}
int main(int argc, const char *argv[])
{
    int i;
    pthread_mutex_init(&g_mutex, NULL);
    pthread_cond_init(&g_cond, NULL);

    for (i = 0; i < CONSUMERS_COUNT; ++i)
    {
        /* code */
        pthread_create(&g_thread[i], NULL, produce, (void*)i);
    }
    for (i = 0; i < PRODUCERS_COUNT; ++i)
    {
        /* code */
        pthread_create(&g_thread[i+CONSUMERS_COUNT], NULL, consume, (void*)i);
    }
    for (i = 0; i < CONSUMERS_COUNT+PRODUCERS_COUNT; ++i)
    {
        /* code */
        pthread_join(g_thread[i], NULL);
    }
    pthread_mutex_destroy(&g_mutex);
    pthread_cond_destroy(&g_cond);
    return 0;
}

 

pthread_cond_wait这个函数的原语:

一。对g_mutex进行解锁,让其他线程可以进入临界区

二。等待条件,直到有线程可以唤醒它,然后让出CPU

三。当被唤醒时,它会重新对g_mutex进行加锁

对于生产者&消费者进行判断为啥使用while而不是if,我们已经之前讨论过了

if值判断一次,而重新上锁之后并不能保证它还满足情况。

时间: 2024-10-12 18:48:53

LINUX学习:生产者&消费者模型复习的相关文章

多线程学习-基础(十二)生产者消费者模型:wait(),sleep(),notify()实现

一.多线程模型一:生产者消费者模型   (1)模型图:(从网上找的图,清晰明了) (2)生产者消费者模型原理说明: 这个模型核心是围绕着一个"仓库"的概念,生产者消费者都是围绕着:"仓库"来进行操作,一个仓库同时只能被一个生产者线程或一个消费者线程所操作,synchronized锁住的也是这个仓库,仓库是一个容器,所以会有边界值,0和仓库可存放上限,在这个上限内,可以设置多种级别,不同的级别可以执行不同的策略流程. (3)本案例使用知识点: Thread.curre

Python学习笔记——进阶篇【第九周】———线程、进程、协程篇(队列Queue和生产者消费者模型)

Python之路,进程.线程.协程篇 本节内容 进程.与线程区别 cpu运行原理 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生产者消费者模型 Queue队列 开发一个线程池 进程 语法 进程间通讯 进程池 参考链接http://www.cnblogs.com/alex3714/articles/5230609.html

生产者消费者模型 学习

简介 得知并发是Java程序员进阶的必经之路,所以从实际代码来先理解 生产者消费者模型 实战 Demo File package demo; /** * 定义商品 * * @author draymonder * */ public class Goods { public final String name; public final int price; public final int id; // public Goods() { // } public Goods(String nam

python2.0_s12_day9之day8遗留知识(queue队列&amp;生产者消费者模型)

4.线程 1.语法 2.join 3.线程锁之Lock\Rlock\信号量 4.将线程变为守护进程 5.Event事件 * 6.queue队列 * 7.生产者消费者模型 4.6 queue队列 queue非常有用,当信息必须安全的在多个线程之间进行数据交换的时候就应该想到queue 所以,queue它能保证数据被安全的在多个线程之间进行交换,那他就是天生的线程安全. queue有那么几种: class queue.Queue(maxsize=0) # 先入先出 class queue.LifoQ

OpenMP实现生产者消费者模型

生产者消费者模型已经很古老了吧,最近写了个OpenMP版的此模型之实现,来分享下. 先说一下模型的大致做法是: 1.生产者需要取任务,生产产品. 2.消费者需要取产品,消费产品. 生产者在生产某个产品之后,要告知消费者此产品已经可以使用了.消费者通过获得可以使用这个信号来取得产品,进一步消费产品. 比如,我们有N个图像需要对每一个图像作滤波或者变换等处理,并且把处理后的结果存到硬盘上. 那么生产者可以将N个图像看成N个任务,每个任务都是独立的,每个任务的计算结果可以看成是产品,消费者就是取这个产

#queue队列 #生产者消费者模型

1 #queue队列 #生产者消费者模型 2 3 #queue队列 #有顺序的容器 4 #程序解耦 5 #提高运行效率 6 7 #class queue.Queue(maxsize=0) #先入先出 8 #class queue.LifoQueue(maxsize=0)最后在第一 9 #class queue.PriorityQueue(maxsize=0) #存储数据时可设置优先级的队列#VIP客户 10 11 #Queue.qsize() 12 #Queue.empty() #return

13 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件  queue队列 生产者消费者模型 Queue队列 开发一个线程池

本节内容 操作系统发展史介绍 进程.与线程区别 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生产者消费者模型 Queue队列 开发一个线程池 进程 语法 进程间通讯 进程池 操作系统发展史 手工操作(无操作系统) 1946年第一台计算机诞生--20世纪50年代中期,还未出现操作系统,计算机工作采用手工操作方式. 手工操作程序员将对应于程序和数据的已穿孔的纸带(或卡片)装入输入机,然后启动输入机把

Python连载38-协程、可迭代、迭代器、生产者消费者模型

一.生产者消费者模型 import multiprocessing from time import ctime def consumer(input_q): print("Into consumer:",ctime()) while True: #处理项 item = input_q.get() print("pull",item,"out of q")#此处替换为有用的工作 input_q.task_done()#发出信号通知任务完成 pri

1-7 生产者消费者模型

一 生产者消费者模型介绍 为什么要使用生产者消费者模型 生产者指的是生产数据的任务,消费者指的是处理数据的任务,在并发编程中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据.同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者.为了解决这个问题于是引入了生产者和消费者模式. 什么是生产者和消费者模式 生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题.生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生