123规则
1个线程安全的队列(同步、互斥)
2种角色的线程(生产者、消费者)
3个规则(生产者与生产者互斥、消费者与消费者互斥、生产者与消费者互斥+同步)
1.1 生产者之关心生产,关心队列是否有空闲空间
1.2 消费者只关心消费,关心队列是否有数据存在
学习123规则的意义
队列:起到了生产者与消费者之间的换种作用
生产者不会因为没人消费而发愁,只需要将生产的数据放进队列当中
消费者不用因为生产者生产了大量的数据而发愁,只需要正常关注正在处理的数据就行。
它好我也好~~
优点
^生产者与消费者解耦
^忙闲不均
^支持高并发
生产者、消费者以及安全队列代码模拟实现
要用到的主要函数
线程安全的队列:
队列: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;
}
代码分析

