【Linux】线程的123规则与生产者消费者(做面人吃面人)模型分析

  1. 123规则

1个线程安全的队列(同步、互斥)

2种角色的线程(生产者、消费者)

3个规则(生产者与生产者互斥、消费者与消费者互斥、生产者与消费者互斥+同步)

1.1 生产者之关心生产,关心队列是否有空闲空间

1.2 消费者只关心消费,关心队列是否有数据存在

  1. 学习123规则的意义

队列:起到了生产者与消费者之间的换种作用

生产者不会因为没人消费而发愁,只需要将生产的数据放进队列当中

消费者不用因为生产者生产了大量的数据而发愁,只需要正常关注正在处理的数据就行。

它好我也好~~

  1. 优点

^生产者与消费者解耦

^忙闲不均

^支持高并发

  1. 生产者、消费者以及安全队列代码模拟实现

要用到的主要函数

线程安全的队列:
队列:std::queue
线程安全:
同步:pthread_mutex_t
互斥:pthread_cond_t
两种角色(生产消费)的线程:
pthread_create

代码模拟

queuesafe.hpp:

#pragma once

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <queue>

/*
 * 线程安全的队列
 * */
class SafeQueue{
    public:
        SafeQueue(){
            pthread_mutex_init(&que_lock_, NULL);
            pthread_cond_init(&cons_cond_, NULL);
            pthread_cond_init(&prod_cond_, NULL);
            capacity_ = 1; //假设队列当中只能放一个元素
        }

        ~SafeQueue(){
            pthread_mutex_destroy(&que_lock_);
            pthread_cond_destroy(&cons_cond_);
            pthread_cond_destroy(&prod_cond_);
        }

        /*
         * 插入接口-生产者调用的
         * */
        void Push(int data){
            pthread_mutex_lock(&que_lock_);
            while(que_.size() >= capacity_){
                pthread_cond_wait(&prod_cond_, &que_lock_);
            }

            que_.push(data);
            printf("i am product, i product %d\n", data);
            pthread_mutex_unlock(&que_lock_);

            /*通知消费者进行消费*/
            pthread_cond_signal(&cons_cond_);
        }

        /*
         * 获取元素的接口-消费者调用的
         * */
        int Pop(){
            pthread_mutex_lock(&que_lock_);
            while(que_.empty()){
                pthread_cond_wait(&cons_cond_, &que_lock_);
            }
            int tmp = que_.front();
            que_.pop();
            printf("i am consume, i consume %d\n", tmp);
            pthread_mutex_unlock(&que_lock_);

            /*通知生产者进行生产*/
            pthread_cond_signal(&prod_cond_);
            return tmp;
        }
    private:
        /* stl当中的queue是线程不安全的, 所以需要进行保护 */
        std::queue<int> que_;
        /* 人为约定队列的大小 */
        size_t capacity_;
        pthread_mutex_t que_lock_;
        /*消费者的条件变量*/
        pthread_cond_t cons_cond_;
        /*生产者的条件变量*/
        pthread_cond_t prod_cond_;

};

cons_prod.cpp:

#include "queuesafe.hpp"

#define THREADCOUNT 1

void* cons_start(void* arg){
    SafeQueue* sq = (SafeQueue*)arg;

    while(1){
        int ret = sq->Pop();
        //printf("i am consume, i consume %d\n", ret);
        if(ret == 999){
            break;
        }
    }
    return NULL;
}

void* prod_start(void* arg){
    /*
     * 获取线程安全的队列
     * */
    SafeQueue* sq = (SafeQueue*)arg;

    int data = 0;
    while(1){
        if(data >= 1000){
            break;
        }
        sq->Push(data);
        //printf("i am product, i product %d\n", data);
        data++;
    }
    return NULL;
}

int main(){
    SafeQueue* sq = new SafeQueue();
    if(sq == NULL){
        perror("new");
        return 0;
    }

    pthread_t cons[THREADCOUNT], prod[THREADCOUNT];
    for(int i = 0; i < THREADCOUNT; i++){
        int ret = pthread_create(&cons[i], NULL, cons_start, (void*)sq);
        if(ret < 0){
            perror("pthread_create");
            return 0;
        }

        ret = pthread_create(&prod[i], NULL, prod_start, (void*)sq);
        if(ret < 0){
            perror("pthread_create");
            return 0;
        }
    }

    /*主线程进行线程等待 - 阻塞等待*/
    for(int i = 0; i < THREADCOUNT; i++){
        pthread_join(cons[i], NULL);
        pthread_join(prod[i], NULL);
    }
    return 0;
}
  1. 代码分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值