使用信号量实现生产者消费者|C语言

本文介绍了使用C语言通过信号量实现多生产者多消费者模型,详细讨论了资源数为1和大于1时的情况。重点在于理解信号量在确保线程同步和防止死锁中的作用,提供了不同资源数下的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

Intro

  • 本文为多生产者多消费者的C语言实现
  • 生产者与消费者针对链表的头结点进行操作
  • 使用的现场同步方法为信号量
  • 本文侧重于理解条件变量的使用
  • 为保证代码简洁,本文代码没有对函数的返回值进行检查,聪明的你一定一定知道如何检查这个小细节(•̀ᴗ•́)و ̑̑
  • 关于互斥锁+条件变量的多生产者多消费者模型实现请参考我的这篇博客

analysis

多生产者多消费者有多个线程,当根据信号量定义的资源数不同,所对应的情况也有所不同,所以在使用信号量去实现多生产者多消费者模型要处理好资源数与多线程之间的关系,在拥有多个资源数时可以配合互斥锁来约束多线程对共享资源的访问

单生产者单消费者

  • 限于篇幅,本篇博客仅简单提及此模型,不展示具体代码
  • 对于单生产者单消费者,资源数只能为1,每次唤醒一个线程,情况并不复杂
  • 若资源数大于1,实际运行就会产生段错误(读写了不该访问的地址)
    在这里插入图片描述

多生产者多消费者

资源数为1

sem_init(&psem, 0, 1);//意义为初始化生产者信号量,用于处理线程,资源数为1
sem_init(&csem, 0, 0);//意义为初始化消费者信号量,用于处理线程,资源数为0

如此定义的好处为:

  • 使生产者先工作

  • 由于资源数为1,程序运行中只有一个线程可被唤醒,不会出现多个线程同时访问共享资源的的情况

  • 无需添加互斥锁对共享资源进行保护

  • SHOW ME THE CODE

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

struct Node {
   
    int number;
    struct Node *next;
};

struct Node *head = NULL;
sem_t psem;//生产者信号量
sem_t csem;//消费者信号量


void *producer(void *arg);//生产者函数
void *consumer(void *arg);//消费者函数

int main(int argc, char **argv)
{
   
    pthread_t ptid[5];//生产者线程
    pthread_t ctid[5];//消费者线程

    sem_init(&psem, 0, 1);//初始化生产者信号量,生产者线程拥有1个信号灯
    sem_init(&csem, 0, 0);//初始化消费者信号量,消费者线程拥有0个信号灯
    //如此这般的意义是使生产者线程先运行

    for(int i = 0; i <
使用记录型信号量(Record Semaphores)可以有效地解决生产者消费者问题,这是一种并发控制机制,在C语言中,你可以通过互斥锁(mutex)、条件变量(condition variable)以及共享数据结构来模拟。以下是使用这种方法实现生产者消费者问题的基本步骤: 1. 定义结构体,包含计数器、生产者列表和消费者列表等信息: ```c typedef struct { int count; // 共享资源的数量 sem_t mutex; // 互斥锁 sem_t cond_producer; // 生产者等待信号 sem_t cond_consumer; // 消费者等待信号 bool empty; // 表示缓冲区是否为空 } producer_consumer_record; ``` 2. 初始化信号量: ```c producer_consumer_record pc = {0, PTHREAD_MUTEX_INITIALIZER, 0, 0, true}; ``` 3. 生产者函数: - 获取互斥锁,检查缓冲区是否满,然后减小计数器并唤醒消费者; - 如果缓冲区不满,生产者继续工作。 ```c void producer(void *arg) { while (true) { pthread_mutex_lock(&pc.mutex); if (!pc.empty && pc.count > 0) { pc.count--; sem_post(&pc.cond_consumer); // 唤醒一个消费者 } else { sem_wait(&pc.cond_producer); // 等待缓冲区空或增加生产 } pthread_mutex_unlock(&pc.mutex); } } ``` 4. 消费者函数: - 获取互斥锁,检查缓冲区是否空,然后增加计数器并唤醒生产者; - 如果缓冲区满,消费者停止工作。 ```c void consumer(void *arg) { while (true) { pthread_mutex_lock(&pc.mutex); if (pc.empty && pc.count < MAX_SIZE) { pc.empty = false; pc.count++; sem_post(&pc.cond_producer); // 唤醒一个生产者 } else { sem_wait(&pc.cond_consumer); // 等待缓冲区非空或减少消费 } pthread_mutex_unlock(&pc.mutex); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值