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

news2024/11/24 20:53:29

简介: 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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1043238.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

服务器端应用的安装

前言&#xff1a;相信看到这篇文章的小伙伴都或多或少有一些编程基础&#xff0c;懂得一些linux的基本命令了吧&#xff0c;本篇文章将带领大家服务器如何部署一个使用django框架开发的一个网站进行云服务器端的部署。 文章使用到的的工具 Python&#xff1a;一种编程语言&…

CSS滚动条详解(::-webkit-scrollbar )

滚动条出现的事件&#xff1a; 当设置定宽或者定高的元素添加overflow:scroll属性&#xff0c;会出现滚动条&#xff0c;但是原生样式的会比较丑影响美观。 <div class"content"><div class"contain"></div> </div>.content {wid…

从C语言到C++:C++入门知识(1)

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下有关C语言的相关知识点&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&#xff1a;从入门到精通 数…

【数据结构--排序】冒泡排序,选择排序,插入排序

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

Unity可视化Shader工具ASE介绍——1、ASE的介绍、安装和简单使用

大家好&#xff0c;我是阿赵&#xff0c;接下来我打算介绍一下Unity引擎的一个好用的可视化Shader编辑插件。这个插件叫做Amplify Shader Editor&#xff0c;下面都会简称为ASE。这一篇主要是讲一下这个插件的获取、安装&#xff0c;和一些简单的界面用法介绍。之后有机会&…

JDK21新特性 有序集合

有序集合 描述常用有序集合体系LinkedHashMapLinkedHashSetLinkedBlockingDequeArrayDeque 三级目录 描述 Java集合体系中&#xff0c;原来就有有序集合实现&#xff0c;但是没有规范支持有序操作的接口。 JDK21 新增了两个接口 SequencedCollection&#xff0c;SequencedMa…

Visual Studio 安装离线插件 vsix 及常用插件

我们在使用 VS 时&#xff0c;经常会在 “扩展”---“扩展管理” 中的 “Visual Studio marketplace” 中寻找适用插件&#xff0c;帮助提升工作效率。但是有时候无法登陆 markeplace&#xff0c;无法查找或安装所需插件&#xff0c;这时候可以手动安装离线插件&#xff0c;完成…

ROS2 从头开始:第 5 部分 - 并发、执行器和回调组

一、说明 让我们回到基础。并发意味着系统或软件可以同时运行许多任务。例如,在单核 CPU 机器上,可以通过使用线程来实现并发。本文探讨了

蓝牙核心规范(V5.4)11.1-LE Audio 笔记之诞生的前世今生

专栏汇总网址:蓝牙篇之蓝牙核心规范学习笔记(V5.4)汇总_蓝牙核心规范中文版_心跳包的博客-CSDN博客 爬虫网站无德,任何非CSDN看到的这篇文章都是盗版网站,你也看不全。认准原始网址。!!! 1.LE Audio应用的场景 这里面有四个场景是LE Audio最初需要应用的场景。比如助…

前端vue实现页面加水印文字 单个页面所有页面加水印(更新版)

随着前端技术的不断发展&#xff0c;组件化开发已经成为现代前端开发的重要趋势。组件化开发可以将大型复杂的系统分解为可重用的独立组件&#xff0c;实现模块解耦、代码复用和开发效率提升。本文将介绍一种基于Vue技术的前端页面加水印文字的组件化实现方式。 一、背景介绍 …

LetCode算法题

注:大佬解答来自LetCode官方题解 88.合并两个有序数组 1.题目 2.个人解答 var merge function (nums1, m, nums2, n) {//合并for (let i 0; i < n; i) {nums1[i m] nums2[i];}// 排序&#xff08;冒泡排序&#xff09;for (let i 0; i < m n; i) {for (let j 0…

扩散模型 - Diffusion Model【李宏毅2023】学习笔记 Part 1

台大官方网站&#xff1a;ML 2023 Spring (ntu.edu.tw) 【生成式AI】Diffusion Model 概念讲解 (1/2)_哔哩哔哩_bilibili PS&#xff1a; 又出新课程了 计算机发展太快了 希望有机会再完整学一遍2233 正式开始上课--------------------------------------------------------…

系统集成|第十七章(笔记)

目录 第十七章 变更管理17.1 项目变更的基本概念17.2 变更管理的基本原则17.3 角色职位与工作程序17.4 相关事宜 上篇&#xff1a;第十六章、信息&#xff08;文档&#xff09;和配置管理 下篇&#xff1a;第十八章、安全管理 第十七章 变更管理 17.1 项目变更的基本概念 变更…

前后端分离的大数据毕设项目之基于Spark+springboot+vue的共享单车数据存储系统的设计与实现

博主介绍&#xff1a;✌全网粉丝10W,前互联网大厂软件研发、集结硕博英豪成立工作室。专注于计算机相关专业毕业设计项目实战6年之久&#xff0c;选择我们就是选择放心、选择安心毕业✌ &#x1f345;由于篇幅限制&#xff0c;想要获取完整文章或者源码&#xff0c;或者代做&am…

使用EPPlus实现C#控件Excel文件内容导入转换

使用EPPlus实现C#控件Excel文件内容导入转换 1.添加EPPlus库 在使用EPPlus库时&#xff0c;你需要确保在项目中添加了正确的引用。你可以通过以下方式添加引用&#xff1a; 打开你的项目。 在“解决方案资源管理器”中&#xff0c;右键单击“引用”并选择“管理NuGet程序包”…

Linux 文件和目录列表(ls 命令)

Linux 文件和目录列表&#xff08;ls 命令&#xff09; 要想知道系统中有哪些文件&#xff0c;可以使用列表命令&#xff08; ls &#xff09;。 文章目录 Linux 文件和目录列表&#xff08;ls 命令&#xff09;一、基本列表功能1. ls 命令基本形式2. ls 命令 -F 参数3. ls 命…

【笔记】ssh link-local 地址登录

1. link-local 地址 IPv6 中在局域网中是使用 link-local 地址通信的。其以 fe80:: 开头。它的形式跟物理地址 mac 关联。只要 mac 没变&#xff0c;那么&#xff0c;link-local 地址就不变。 2. 使用 link-local 地址的场景 自己搭建了一个局域网&#xff0c;有两台主机&am…

Spring整合RabbitMQ——消费者

1.配置consumer xml配置文件 2. 实现MessageListener接口 并重写onMessage方法

UG NX二次开发(C++)-采用NXOpen方法创建同步建模中的偏置曲面

文章目录 1、 前言2、在UG NX中的偏置操作3、采用NXOpen二次开发偏置曲面4、测试方法4.1 创建UI界面4.2 创建工程4.3 生成结果1、 前言 在UG NX二次开发(C++)中,通过UFun(Open C)函数进行开发的文章比较多,我们这个专栏的博客是主要采用NXOpen开发的,对于这二者的区别,我…

【面试题】面试官:说说你对js中的 防抖 和 节流 的理解

前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 表妹一键制作自己的五星红旗国庆头像&#xff0c;超好看 前言 看到这个题目我想肯定会有人说&#xff1a;不会吧&#xff0c;都3202年了&#xff0c;还…