C++之mutex、operator()、lambda应用总结(二百三十一)

2023-09-22 13:11:48

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!

优质专栏:Audio工程师进阶系列原创干货持续更新中……】🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

欢迎关注Android系统攻城狮

1.前言

本篇目的:理解C++之mutex互斥量与lambda函数应用总结。

2.lambda函数概念与用法

在C++中,lambda表达式是一种匿名函数的语法形式,可以在需要函数对象的地方直接定义和使用函数。lambda表达式的实现原理是通过创建一个匿名的函数对象,这个函数对象重载了operator()运算符,使得可以像函数一样进行调用。

lambda表达式的一般语法形式如下:

[capture-list] (parameter-list) -> return-type { function-body }

其中,capture-list是捕捉列表,用于指定lambda表达式中使用的外部变量。parameter-list是参数列表,用于指定lambda表达式的参数。return-type是返回类型,用于指定lambda表达式的返回值类型。function-body是函数体,包含了lambda表达式的实际执行逻辑。

Lambda表达式的应用原理是通过简化函数对象的定义和使用,可以更方便地编写匿名的函数和进行函数式编程。它常用于以下几个场景:

  1. 函数传递:可以直接将lambda表达式作为函数参数,以简化回调函数的定义和传递。
  2. 算法逻辑:可以直接在算法函数中使用lambda表达式,以定义算法的具体执行逻辑。
  3. 数据转换:可以通过lambda表达式进行数据的转换和过滤,实现数据处理的灵活性和可读性。

3.mutex函数概念与用法

互斥锁(mutex)是一种用于同步线程的机制。它可以确保在多个线程访问共享资源时,只有一个线程能够执行临界区代码,以防止并发访问导致的数据竞争问题。

互斥锁的实现原理通常涉及操作系统提供的底层同步原语或硬件指令。以下是一个简单的概述:

  1. 创建互斥锁:在C++中,可以使用std::mutex类来创建互斥锁对象。在创建时,该对象处于未锁定状态。

  2. 加锁(Lock):当一个线程想要进入临界区时,它首先必须尝试获取互斥锁的所有权。如果互斥锁未被锁定,则该线程会成功地获得锁,并进入临界区。如果互斥锁已经被其他线程锁定,则当前线程会被阻塞,直到该锁被释放为止。

  3. 临界区操作:一旦线程获得了互斥锁的所有权,它就可以执行临界区内的操作。这些操作通常是对共享资源进行读取或写入。

  4. 解锁(Unlock):在线程完成临界区操作后,它必须释放互斥锁,以便其他线程能够获取锁并进入临界区。通过调用互斥锁对象的unlock()方法,线程可以释放锁。

使用互斥锁可以有效地确保在任何给定时刻只有一个线程可以访问共享资源,从而避免数据竞争和并发访问的问题。然而,过度使用互斥锁可能会导致线程间的竞争,从而影响性能。因此,在设计并发应用程序时,需要仔细权衡使用互斥锁的粒度和范围。

4.operator()函数概念与用法

在C++中,operator()是一种函数调用运算符(function call operator),也被称为仿函数(functor)。它允许将一个类的对象像函数一样进行调用,使得对象可以具有函数的行为。

operator()的实现原理涉及到类的重载运算符和函数调用机制。以下是一些关键的原理:

  1. 重载运算符:在C++中,运算符可以被重载,也就是可以重新定义运算符的行为。通过重载运算符,可以指定在使用运算符时编译器应该执行的操作。

  2. 类的成员函数:operator()是一个类的成员函数,因此它只能在类的对象上进行调用。它可以像普通的成员函数一样,访问类的成员变量和其他成员函数。

  3. 函数调用机制:当我们使用对象来调用operator()时,编译器会将其解析为函数调用,并将调用参数传递给这个函数。调用operator()的语法类似于调用函数的语法。

  4. 实现灵活性:通过实现operator(),我们可以将一个对象实例化为可以像函数一样使用的可调用对象。这种灵活性使得我们可以将对象作为函数对象传递给算法或者将其用于其他需要函数作为参数的场合。

使用operator()可以为类对象带来函数的行为特征,使得这些对象可以被直接调用,并进行一些定义的操作。通过重载运算符,我们可以自定义operator()的行为,使其在对象被调用时执行特定的操作逻辑。

5.应用实例

v1.0 mutex与lambda函数应用

#include <iostream>
#include <memory>
#include <mutex>

class TEST {
public:
  int count = 100;
  std::shared_ptr<TEST> comp;
};

int main() {
  std::mutex mState;
  std::shared_ptr<TEST> comp;

  auto checkAllocated = [&]() {
    std::unique_lock<std::mutex> lock(mState);

    comp = std::make_shared<TEST>();
    return comp->count;
  };

  int result = checkAllocated();
  std::cout << "count: " << result << std::endl;

  return 0;
}

v2.0 operator()无参仿函数例子

#include <iostream>


class TEST {
public:
  int operator()(int x){
    this->count = x;
    return x;
  }
  int count;
};

int main() {
  TEST test;

  int result = test(5);
  std::cout << "data value: " << result << std::endl;

  return 0;
}

v3.0 operator()有一个参数仿函数例子

#include <iostream>


class TEST {
public:
  int operator()(int x){
    this->count = x;
    return x;
  }
  int count;
};

int main() {
  TEST test;

  int result = test(5);
  std::cout << "data value: " << result << std::endl;

  return 0;
}

注意:operator()仿函数不能使用构造函数初始化列表方式,以下用法是错误的。

class TEST {
public:
  int operator()(int x): count(x){
    return x;
  }
 int count;
 };

4.0 mutex、operator、lambda函数组合应用

#include <iostream>
#include <memory>
#include <mutex>

class TEST {
public:
  int count = 100;
  std::shared_ptr<TEST> comp;
};

template <typename T>
class Mutexed {
public:
  explicit Mutexed(T data) : m_data(std::move(data)) {
    printf("xxx--------->%s(), line = %d\n",__FUNCTION__,__LINE__);
  }
  
  //Mutexed定义了自己的operator()函数,可以定义对象,对象像函数一样使用。
  template <typename F>
  auto operator()(F&& func) {
    std::lock_guard<std::mutex> lock(m_mutex);
    return std::forward<F>(func)(m_data);
  }

private:
  T m_data;
  std::mutex m_mutex;
};

int main() {
  //1.使用shared_ptr指向TEST的智能指针comp,make_shared创建TEST对象并赋值给comp
  std::shared_ptr<TEST> comp = std::make_shared<TEST>(); 
  comp->count = 200;
	
  //2.调用嗯Mutexed构造函数,并传入指向TEST的智能指针类型mState,并且将comp赋值给mState.
  Mutexed<std::shared_ptr<TEST>> mState(comp);

  auto checkAllocated = [&]() {
    //mState是Mutexed的operator()函数,这里相当于 调用mState(参数)回调函数,传入参数即可。它在实例化出mState时,已经将comp传给了m_data,这里调用state->count,相当于调用m_data->count.
    return mState([](const std::shared_ptr<TEST>& state) {
      return state->count;
    });
  };

  int result = checkAllocated();
  std::cout << "count: " << result << std::endl;


  return 0;
}

更多推荐

ELK 企业级日志分析系统

----------------------ELK概述----------------------------------------1、ELK简介ELK平台是一套完整的日志集中处理解决方案,将ElasticSearch、Logstash和Kiabana三个开源工具配合使用,完成更强大的用户对日志的查询、排序、统计需求

2023-09-18 monetdb-GDK和BAT-分析与思考

摘要:GDK作为moentdb的最核心的内核,可以看作是物理计划的执行,以及与磁盘IO直接进行交互.而物理列的数据结构,就是BAT.所以GDK也可以看作是对BAT的操作的模块,BAT是GDK操作的对象,是GDK的一部分.GDK和BAT的名字其实无关紧要,重要的是这些模块所承载的功能.GDK:monetdb的最核心的内核

数据结构——二叉搜索树

二叉搜索树是二叉树的一种特殊形式。二叉搜索树具有以下性质:1.每个节点中的值必须大于(或等于)其左侧子树中的任何值2.每个节点中的值必须小于(或等于)其右侧子树中的任何值。像普通的二叉树一样,我们可以按照前序、中序和后序来遍历一个二叉搜索树。但是值得注意的是,对于二叉搜索树,我们可以通过中序遍历得到一个递增的有序序列。

Arm发布 Neoverse V2 和 E2:下一代 Arm 服务器 CPU 内核

9月14日,Arm发布了新的处理器内核:V2和E2,在官网已经可以看到相关的TRM手册了。。四年前,Arm发布了Neoverse系列的CPU设计。Arm决定加大力度进军服务器和边缘计算市场,专门为这些市场设计ArmCPU内核,而不仅仅是回收以消费者为中心的Cortex-A设计。因此,Arm开始以更积极的方式进军基础设施

《C++ primer plus》精炼(OOP部分)——对象和类(5)

“学习是照亮心灵的火炬,它永不熄灭,永不止息。”文章目录类的自动和强制类型转换原始类型转换为自定义类型将自定义类型转换为原始类型类的自动和强制类型转换原始类型转换为自定义类型可以用一个参数的构造函数来实现,例如:classStudent{strings;intgrade;Student(inti);}intmain(v

用php&&redis发布订阅模式实现批量发送短信

使用Redis的发布订阅模式来实现批量发送短信是一种有效的方式,可以将短信任务发布到一个频道,然后多个订阅者(短信发送程序)从该频道获取任务并执行发送。以下是几个示例,演示如何使用Redis的发布订阅模式来实现批量发送短信:注意:以下示例为演示代码,实际应用中可能需要更多的错误处理、性能优化和安全措施。发布者-将短信任

直播流⻚⾯内存优化⽅案

本文字数:6628字预计阅读时间:39分钟01项目背景介绍项目中直播流每场直播由一张直播图片作为展示入口,用于提示用户此直播的概要。如下图:然而直播图片和容器的宽高比例出现不一致的情况。针对此情况,采取背景图contentmode展示为aspectFill且高斯模糊,上层高清图为aspectfit,给用户一种图片填满且

(2023 最新版)IntelliJ IDEA 下载安装及配置教程

IntelliJIDEA下载安装教程(图解)IntelliJIDEA简称IDEA,由JetBrains公司开发,是Java编程语言开发的集成环境,具有美观,高效等众多特点。在智能代码助手、代码自动提示、重构、J2EE支持、各类版本工具(Git、SVN等)、JUnit、CVS整合、代码分析、创新的GUI设计等方面都有很好

Qt中表格属性相关操作,调整表格宽度高度自适应内容等

1表格列宽设置利用Qtdesigner设计,可以通过改变表头的列宽从而保证内容不会被遮盖,输入空格的方式增加表头的长度,比如表头为"Value",则改成"Value",可以扩展列默认的宽度,保证后面添加的数据不会遮盖了。2表头颜色在样式表中设置,双击编辑表头内容时,属性可设置字体颜色,但是无法设置背景色,QTableW

APP推荐:安卓系统的开屏广告自动跳过助手

今天给大家推荐一款安卓系统的开屏广告自动跳过助手,感兴趣的朋友可以下载试试看!一、软件简介安卓系统的开屏广告自动跳过助手自动跳过软件的实现,一般都是基于安卓的Accessibility“无障碍服务”实现。开启了无障碍服务的软件,可以获取屏幕上的任何内容,从而可以检测广告,帮助用户自动跳过。因此,使用广告跳过程序,最大的

敦煌网“星云计划”:助商家开拓新流量和新玩法,测评补单快速提高产品排名和销量

敦煌网是一家以丝绸之路文化为主题的电商平台,为消费者提供各类优质商品。敦煌网通过推出“星云计划”,帮助中国商家实现业务增长和品牌推广。该计划为商家提供流量、营销、工具、网红带货、海外推广、支付、物流、回款、服务保障等资源,助力中国品牌出海。作为敦煌网年度重点项目,“星云计划”为商家提供覆盖新流量、新玩法、星级权益、星级

热文推荐