c++生产者消费者模型实现(使用锁和信号量)
C++ 实现 模型 消费者 信号量 生产者 使用
2023-09-14 09:12:44 时间
生产者和消费者模型必须要用到锁和信号量,锁是为了线程同步,即是防止多个线程同时改动公共数据,使得多个线程在访问公共资源时串行执行。
信号量是当生产者生产出来数据后,通知消费者。
当读数据线程准备访问公共数据,但此时已经被消费完了,此时需要阻塞,直到生产者生产出来再通知消费者,这种情况下必须使用信号量,锁不能代替。
推荐一套音视频免费课程,笔者听完了,nice!免费报名可听!
免费音视频课程连接,点击此处
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
// 链表的节点
struct Node
{
int number;
struct Node* next;
};
// 定义条件变量, 控制消费者线程
pthread_cond_t cond;
// 互斥锁变量
pthread_mutex_t mutex;
// 指向头结点的指针
struct Node * head = NULL;
// 生产者的回调函数
void* producer(void* arg)
{
// 一直生产
while(1)
{
pthread_mutex_lock(&mutex);
// 创建一个链表的新节点
struct Node* pnew = (struct Node*)malloc(sizeof(struct Node));
// 节点初始化
pnew->number = rand() % 1000;
// 节点的连接, 添加到链表的头部, 新节点就新的头结点
pnew->next = head;
// head指针前移
head = pnew;
printf("+++producer, number = %d, tid = %ld\n", pnew->number, pthread_self());
pthread_mutex_unlock(&mutex);
// 生产了任务, 通知消费者消费
pthread_cond_broadcast(&cond);
// 生产慢一点
sleep(rand() % 3);
}
return NULL;
}
// 消费者的回调函数
void* consumer(void* arg)
{
while(1)
{
pthread_mutex_lock(&mutex);
// 一直消费, 删除链表中的一个节点
// if(head == NULL) // 这样写有bug
while(head == NULL)
{
// 任务队列, 也就是链表中已经没有节点可以消费了
// 消费者线程需要阻塞
// 线程加互斥锁成功, 但是线程阻塞在这行代码上, 锁还没解开
// 其他线程在访问这把锁的时候也会阻塞, 生产者也会阻塞 ==> 死锁
// 这函数会自动将线程拥有的锁解开
pthread_cond_wait(&cond, &mutex);
// 当消费者线程解除阻塞之后, 会自动将这把锁锁上
// 这时候当前这个线程又重新拥有了这把互斥锁
}
// 取出链表的头结点, 将其删除
struct Node* pnode = head;
printf("--consumer: number: %d, tid = %ld\n", pnode->number, pthread_self());
head = pnode->next;
free(pnode);
pthread_mutex_unlock(&mutex);
sleep(rand() % 3);
}
return NULL;
}
int main()
{
// 初始化条件变量
pthread_cond_init(&cond, NULL);
pthread_mutex_init(&mutex, NULL);
// 创建5个生产者, 5个消费者
pthread_t ptid[5];
pthread_t ctid[5];
for(int i=0; i<5; ++i)
{
pthread_create(&ptid[i], NULL, producer, NULL);
}
for(int i=0; i<5; ++i)
{
pthread_create(&ctid[i], NULL, consumer, NULL);
}
// 释放资源
for(int i=0; i<5; ++i)
{
// 阻塞等待子线程退出
pthread_join(ptid[i], NULL);
}
for(int i=0; i<5; ++i)
{
pthread_join(ctid[i], NULL);
}
// 销毁条件变量
pthread_cond_destroy(&cond);
pthread_mutex_destroy(&mutex);
return 0;
}
感谢链接:
https://subingwen.cn/linux/thread-sync/#5-2-%E7%94%9F%E4%BA%A7%E8%80%85%E5%92%8C%E6%B6%88%E8%B4%B9%E8%80%85
相关文章
- C++中数据共享的实现机制
- C++内存池的实现和原理(二)
- C++实现读写文件
- java实现第二届蓝桥杯地铁换乘(C++)
- C/C++每日一练(20230219)
- C语言/C++常见习题问答集锦(三十六)之两个浮点数相加的遐想
- paddle 44 用onnxruntime实现ppyoloe模型的部署(含python和c++版本),支持batchsize
- paddle 43 用onnxruntime实现ppyoloe模型的部署(含python和c++版本)
- Algorithm:C++语言实现之链表相关算法(链表相加、链表的部分翻转、链表划分、链表去重、重复元素全部删除)
- c++11随记:std::bind及 std::placeholders
- C++对象模型之RTTI的实现原理
- 大话设计模式C++实现-第14章-观察者模式
- AI模型设计:Ubuntu18.04完美编译在阿里云镜像源tensorflow C++并实现深度学习计算【编译方法与测试深度学习C++源码已开源】
- AI模型设计:配置C++版本pytorch(libtorch 1.12)开发环境以及demo源码的实现
- C++之stringstream(字符串与数字相互转换)(七十四)
- C++ string与vector<float>类型相互转换之stringstream(十九)
- c++实现精确计时
- C++ 採集音频流(PCM裸流)实现录音功能
- 在OpenCV里实现numpy的C++库扩展
- 2021 CCF非专业级别软件能力认证第一轮 (CSP-J)入门级 C++答案及解析
- VC++中实现INI文件读写的方法和示例
- C/C++学习笔记 C++中的智能指针
- 每天积累一个C++小技巧