博客
关于我
Linux系统编程40:多线程之基于环形队列的生产者与消费者模型
阅读量:207 次
发布时间:2019-02-28

本文共 2833 字,大约阅读时间需要 9 分钟。

什么是信号量

在处理多线程程序时,临界区是需要保护的关键资源,但单独使用锁会导致效率低下。为了优化资源使用效率,信号量(Semaphore)提供了一种更灵活的资源管理机制。信号量可以看作是一个计数器,用于跟踪临界资源的可用数量。它通过两个操作——P(请求)和V(释放)来管理资源的分配和回收。

在传统的锁机制中,只能允许一个线程进入临界区,这限制了资源利用的潜力。信号量通过将临界区划分为多个独立的区域来解决这个问题。每个区域可以允许一个线程进入,从而提高整体的资源利用率。然而,如何处理超过指定区域数量的线程请求?这是信号量的核心作用。

信号量由两个部分组成:一个值(通常用S表示)和一个指针(用P指向等待该信号量的线程)。S的值反映了临界资源的状态:

  • 如果S ≥ 0,表示有相应数量的临界资源可用。
  • 如果执行P操作,请求分配一个资源,S会减一;如果S < 0,表示没有可用资源,此时S的绝对值表示等待该资源的线程数。请求者必须等待其他线程释放资源后才能继续运行。
  • 执行V操作时,释放一个资源,S会加一。

信号量的基本操作

在使用信号量之前,需要创建一个sem_t类型的变量。具体步骤如下:

  • 包含必要的头文件
  • #include 
    1. 初始化信号量:使用sem_init函数初始化信号量。该函数的参数包括信号量变量、共享标志和初始值。
    2. int sem_init(sem_t* sem, int pshared, unsigned int value);
      • pshared一般设置为0,表示信号量仅在当前进程中使用。
      • value指定信号量的初始值。
      1. 销毁信号量:当信号量不再需要时,使用sem_destroy函数销毁它。
      2. int sem_destroy(sem_t* sem);
        1. 信号量操作接口:POSIX信号量定义了sem_waitsem_post两个函数,分别对应P操作和V操作。
        2. int sem_wait(sem_t* sem);int sem_post(sem_t* sem);

          基于环形队列的生产者与消费者模型

          传统的阻塞队列模型中,生产者和消费者是串行运行的,这限制了它们的并行效率。环形队列(Circular Queue)通过并行化生产者和消费者来解决这一问题。每个生产者负责向队列中添加数据,每个消费者负责从队列中读取数据。

          在这种模型中,生产者和消费者都需要信号量来管理资源:

          • 消费者关心队列中是否有数据(P操作)。
          • 生产者关心队列中是否有空格(P操作)。

          通过信号量,生产者和消费者可以在不竞争的情况下并行运行。当队列为空时,消费者会被阻塞,直到生产者添加数据。当队列满时,生产者也会被阻塞,直到消费者释放空格。

          代码实现

          #include 
          #include
          #include
          #include
          using namespace std;class CircularQueue {private: vector
          v; int _cap; sem_t data; sem_t blank; int com_index; int pro_index;public: CircularQueue(int cap = 10) : _cap(cap) { v.resize(_cap); sem_init(&data, 0, 0); sem_init(&blank, 0, _cap); com_index = 0; pro_index = 0; } ~CircularQueue() { sem_destroy(&data); sem_destroy(&blank); } void Put(const int& val) { sem_wait(&blank); v[pro_index] = val; pro_index++; pro_index %= _cap; sem_post(&data); } void Get(int& val) { sem_wait(&data); val = v[com_index]; com_index++; com_index %= _cap; sem_post(&blank); }};

          测试程序

          #include "circular_queue.hpp"#include 
          CircularQueue* bq = new CircularQueue(10);void* consumer_run(void* arg) { while (1) { int data; bq->Get(data); printf("%s拿到数据:%d\n", (char*)arg, data); }}void* productor_run(void* arg) { int cout = 1; while (1) { if (cout == 11) { cout = 1; } bq->Put(cout); printf("%s放进数据:%d\n", (char*)arg, cout); cout++; sleep(1); }}int main() { pthread_t con, pro; pthread_create(&con, nullptr, consumer_run, (void*)"消费者"); pthread_create(&pro, nullptr, productor_run, (void*)"生产者"); pthread_join(con, nullptr); pthread_join(pro, nullptr); delete bq; return 0;}

          ###效果展示

          在本例中,生产者以较慢的速度工作(每秒生产一个数据),而消费者可以并行处理多个数据。这样可以避免生产者成为瓶颈,提升整体系统的效率。通过信号量的管理,生产者和消费者能够在不竞争的情况下高效运行。

    转载地址:http://visi.baihongyu.com/

    你可能感兴趣的文章
    NIFI从MySql中增量同步数据_通过Mysql的binlog功能_实时同步mysql数据_配置数据路由_实现数据插入数据到目标数据库_实际操作03---大数据之Nifi工作笔记0042
    查看>>
    NIFI从MySql中离线读取数据再导入到MySql中_03_来吧用NIFI实现_数据分页获取功能---大数据之Nifi工作笔记0038
    查看>>
    NIFI从PostGresql中离线读取数据再导入到MySql中_带有数据分页获取功能_不带分页不能用_NIFI资料太少了---大数据之Nifi工作笔记0039
    查看>>
    NIFI同步MySql数据_到SqlServer_错误_驱动程序无法通过使用安全套接字层(SSL)加密与SQL Server_Navicat连接SqlServer---大数据之Nifi工作笔记0047
    查看>>
    Nifi同步过程中报错create_time字段找不到_实际目标表和源表中没有这个字段---大数据之Nifi工作笔记0066
    查看>>
    NIFI大数据进阶_FlowFile拓扑_对FlowFile内容和属性的修改删除添加_介绍和描述_以及实际操作---大数据之Nifi工作笔记0023
    查看>>
    NIFI大数据进阶_NIFI的模板和组的使用-介绍和实际操作_创建组_嵌套组_模板创建下载_导入---大数据之Nifi工作笔记0022
    查看>>
    NIFI大数据进阶_NIFI监控的强大功能介绍_处理器面板_进程组面板_summary监控_data_provenance事件源---大数据之Nifi工作笔记0025
    查看>>
    NIFI大数据进阶_内嵌ZK模式集群1_搭建过程说明---大数据之Nifi工作笔记0015
    查看>>
    NIFI大数据进阶_外部ZK模式集群1_实际操作搭建NIFI外部ZK模式集群---大数据之Nifi工作笔记0017
    查看>>
    NIFI大数据进阶_离线同步MySql数据到HDFS_01_实际操作---大数据之Nifi工作笔记0029
    查看>>
    NIFI大数据进阶_离线同步MySql数据到HDFS_02_实际操作_splitjson处理器_puthdfs处理器_querydatabasetable处理器---大数据之Nifi工作笔记0030
    查看>>
    NIFI大数据进阶_连接与关系_设置数据流负载均衡_设置背压_设置展现弯曲_介绍以及实际操作---大数据之Nifi工作笔记0027
    查看>>
    NIFI数据库同步_多表_特定表同时同步_实际操作_MySqlToMysql_可推广到其他数据库_Postgresql_Hbase_SqlServer等----大数据之Nifi工作笔记0053
    查看>>
    NIFI汉化_替换logo_二次开发_Idea编译NIFI最新源码_详细过程记录_全解析_Maven编译NIFI避坑指南001---大数据之Nifi工作笔记0068
    查看>>
    NIFI集群_内存溢出_CPU占用100%修复_GC overhead limit exceeded_NIFI: out of memory error ---大数据之Nifi工作笔记0017
    查看>>
    NIFI集群_队列Queue中数据无法清空_清除队列数据报错_无法删除queue_解决_集群中机器交替重启删除---大数据之Nifi工作笔记0061
    查看>>
    NIH发布包含10600张CT图像数据库 为AI算法测试铺路
    查看>>
    Nim教程【十二】
    查看>>
    Nim游戏
    查看>>