C++中锁与原子操作的区别及取舍策略

article/2025/6/10 5:01:52

在这里插入图片描述

文章目录

      • 锁与原子操作的基本概念
        • 锁(Lock)
        • 原子操作(Atomic Operations)
      • 锁与原子操作的区别
        • 1. **功能**
        • 2. **性能**
        • 3. **复杂性**
        • 4. **适用场景**
      • 锁与原子操作的取舍策略
        • 1. **简单变量操作**
        • 2. **复杂共享资源**
        • 3. **性能敏感场景**
        • 4. **避免死锁**
        • 5. **内存顺序**
      • 示例对比
        • 使用锁
        • 使用原子操作
      • 总结

在多线程编程中,同步机制是确保线程安全的关键。C++提供了多种同步工具,其中锁(如 std::mutex)和原子操作(如 std::atomic)是最常用的两种。它们在功能和性能上各有特点,适用于不同的场景。本文将详细探讨锁和原子操作的区别,并提供一些关于如何选择它们的建议。

锁与原子操作的基本概念

锁(Lock)

锁是一种同步机制,用于保护共享资源,防止多个线程同时访问。C++标准库提供了多种锁的实现,如std::mutexstd::recursive_mutex等。使用锁时,线程在访问共享资源之前必须先获取锁,访问完成后释放锁。

std::mutex mtx;void shared_resource_access() {mtx.lock();// 访问共享资源mtx.unlock();
}
原子操作(Atomic Operations)

原子操作是一种特殊的操作,它保证操作的不可分割性,即在多线程环境下,操作不会被其他线程中断。C++11引入了std::atomic,用于实现原子操作。

std::atomic<int> counter(0);void increment_counter() {counter.fetch_add(1, std::memory_order_relaxed);
}

锁与原子操作的区别

1. 功能
  • :用于保护共享资源,防止多个线程同时访问。锁的作用范围通常是一个代码块或函数。
  • 原子操作:用于保证单个操作的原子性,通常用于简单的变量操作(如读取、更新、比较等)。
2. 性能
  • :锁的开销较大,尤其是当多个线程竞争锁时。锁的获取和释放需要系统调用,可能会导致线程阻塞和上下文切换。
  • 原子操作:原子操作的开销较小,通常由硬件直接支持,性能更高。
3. 复杂性
  • :使用锁时需要小心避免死锁、锁顺序问题等。锁的使用较为复杂,需要合理设计锁的粒度。
  • 原子操作:原子操作相对简单,不需要担心死锁问题,但需要合理选择内存顺序(如std::memory_order)。
4. 适用场景
  • :适用于保护复杂的共享资源或需要多个操作同步的场景。
  • 原子操作:适用于简单的变量操作,如计数器、标志位等。

锁与原子操作的取舍策略

在选择锁和原子操作时,需要根据具体需求和场景进行权衡。以下是一些选择的建议:

1. 简单变量操作

如果需要对单个变量进行简单的操作(如读取、更新、比较等),优先选择原子操作。原子操作的性能更高,且使用起来相对简单。

std::atomic<int> counter(0);void increment_counter() {counter.fetch_add(1, std::memory_order_relaxed);
}
2. 复杂共享资源

如果需要保护复杂的共享资源(如数据结构、文件句柄等),或者需要多个操作同步完成,优先选择锁。锁可以保护整个代码块,确保线程安全。

std::mutex mtx;
std::vector<int> shared_vector;void modify_shared_vector() {mtx.lock();shared_vector.push_back(42);mtx.unlock();
}
3. 性能敏感场景

在性能敏感的场景中,尽量使用原子操作。原子操作的开销较小,不会导致线程阻塞和上下文切换。如果必须使用锁,尽量选择细粒度的锁,减少锁的持有时间。

4. 避免死锁

如果使用锁,需要特别注意避免死锁。合理设计锁的顺序,避免嵌套锁的使用。如果可能,尽量使用原子操作来简化同步机制。

5. 内存顺序

使用原子操作时,需要合理选择内存顺序。std::memory_order提供了多种内存顺序选项,如std::memory_order_relaxedstd::memory_order_acquirestd::memory_order_release等。选择合适的内存顺序可以提高性能,同时保证线程安全。

示例对比

使用锁
std::mutex mtx;
int counter = 0;void increment_counter() {mtx.lock();counter++;mtx.unlock();
}
使用原子操作
std::atomic<int> counter(0);void increment_counter() {counter.fetch_add(1, std::memory_order_relaxed);
}

在上述例子中,使用原子操作的版本性能更高,代码也更简洁。但如果需要保护一个复杂的数据结构,锁可能是更好的选择。

总结

锁和原子操作是C++中两种重要的同步机制,各有优缺点。锁适用于保护复杂的共享资源,原子操作适用于简单的变量操作。在选择时,需要根据具体需求、性能要求和代码复杂性进行权衡。以下是一些选择的要点:

  • 简单变量操作:优先选择原子操作。
  • 复杂共享资源:优先选择锁。
  • 性能敏感场景:优先选择原子操作。
  • 避免死锁:合理设计锁的使用,尽量使用原子操作简化同步。

希望本文的介绍和建议能够帮助你在多线程编程中更好地选择锁和原子操作。如果你对某个具体场景有疑问,欢迎在评论区留言讨论。


http://www.hkcw.cn/article/HueBCHvBHt.shtml

相关文章

知识拓展卡———————RSTP与MSTP的简要说明

我们在之前的学习过程中了解了STP&#xff08;生成树协议&#xff09;的各个端口角色选举的相关概念&#xff0c;今天我们再来拓展一下关于STP的扩展性知识点MSTP与RSTP。 目录 RSTP&#xff08;Rapid Spanning Tree Protocol,快速生成树协议&#xff09;: 端口角色&#xf…

NSSCTF [LitCTF 2025]test_your_nc

[复现]绕过学的还是太差了&#xff0c;多积累吧 ​​​​​​题目 题目: 给了一个python文件 #!/bin/python3 import osprint("input your command")blacklist [cat,ls, ,cd,echo,<,${IFS},sh,\\]while True:command input()for i in blacklist:if i in com…

(10)Fiddler抓包-Fiddler如何设置捕获Firefox浏览器的Https会话

1.简介 经过上一篇对Fiddler的配置后&#xff0c;绝大多数的Https的会话&#xff0c;我们可以成功捕获抓取到&#xff0c;但是有些版本的Firefox浏览器仍然是捕获不到其的Https会话&#xff0c;需要我们更进一步的配置才能捕获到会话进行抓包。 2.环境 1.环境是Windows 10版…

持续领跑中国异地组网路由器市场,贝锐蒲公英再次登顶销量榜首

作为国产远程连接SaaS服务的创领者&#xff0c;贝锐持续引领行业发展&#xff0c;旗下贝锐蒲公英异地组网路由器&#xff0c;凭借出色的技术实力和市场表现&#xff0c;斩获2024年线上电商平台市场销量份额中国第一的佳绩&#xff0c;充分彰显了其在网络解决方案与异地组网领域…

Redis底层数据结构之深入理解跳表(2)

上一篇文章中我们详细讲述了跳表的增添、查找和修改的操作&#xff0c;这篇文章我们来讲解一下跳表在多线程并发时的安全问题。在Redis中&#xff0c;除了网络IO部分和大文件的后台复制涉及到多线程外&#xff0c;其余任务执行时全部都是单线程&#xff0c;这也就意味着在Redis…

振动力学:有阻尼单自由度系统(简谐力激励的受迫振动)

本文讨论外力作用下的单自由度系统的受迫振动&#xff0c;特别是详细讨论了系统的共振特性。 1. 受迫振动的解及其组成 根据文章1和2的描述&#xff0c;此时简谐力外力 f ( t ) f 0 sin ⁡ ( ω t ) f(t) f_0 \sin(\omega t) f(t)f0​sin(ωt)。因此振动方程为&#xff1a;…

Vert.x学习笔记-EventLoop与Handler的关系

Vert.x学习笔记 一、底层机制&#xff1a;事件驱动的核心引擎二、协作流程&#xff1a;事件分发与执行三、线程安全&#xff1a;EventLoop与Handler的约束四、性能优化&#xff1a;最佳实践与注意事项五、典型场景与架构设计六、总结 在Vert.x中&#xff0c;**EventLoop&#x…

DevEco Studio的使用

IDE环境的搭建 快速开始 因为本版本的DevEco Studio为一体化版本&#xff0c;已经包含了SDK&#xff0c;构建插件&#xff0c;ohpm等工具&#xff0c;所以您 在安装完成后即可开箱即用&#xff0c;进行工程开发&#xff0c;无需配置环境。首先看一下安装DevEco Studio的相关流…

手动删除网页上的禁止复制事件

以Edge浏览器为环境、以网络上一个文档为例。 右击页面&#xff0c;打开【检查】工具。选择元素&#xff0c;打开【事件侦听器】&#xff1a; 展开copy&#xff0c;删除里面的事件&#xff1a; 选中文字&#xff0c;进行复制

【MATLAB去噪算法】基于CEEMD联合小波阈值去噪算法(第三期)

02.去噪算法原理 1.引言 传统EMD方法存在模态混叠问题&#xff0c;即信号成分在不同IMF分量中出现碎片化分布。为改进这一问题&#xff0c;Huang等&#xff08;1999&#xff09;提出间歇性测试算法&#xff0c;但效果有限。Wu和Huang&#xff08;2009&#xff09;发展的集合经…

Semi-Supervised Neuron Segmentation via Reinforced Consistency Learning

perturbed counterpart x u ′ ^{u} u′ waterz环境不好满足&#xff0c;不建议复现

R语言使用随机过采样(Random Oversampling)平衡数据集

随机过采样&#xff08;Random Oversampling&#xff09;是一种用于平衡数据集的技术&#xff0c;常用于机器学习中处理类别不平衡问题。当某个类别的样本数量远少于其他类别时&#xff08;例如二分类中的正负样本比例悬殊&#xff09;&#xff0c;模型可能会偏向多数类&#x…

pcie 日常问答-20250528

问题均来自工作总结&#xff0c;面经问题&#xff1b;多为发散性问题&#xff1b;大多均会结合S IP rtl实现进行细致分析。 1. dllp包有哪些类型&#xff1f;dllp主要功能是干甚呢的&#xff1f; dllp是一个点到点的传输&#xff08;传输过程中没有任何标识&#xff09;&#…

ADK实战-基于ollama+qwen3实现外部工具串行调用

0 环境准备 1 开发环境准备 1.1 创建项目python环境 1.2 在pycharm创建项目 1.3 安装项目依赖 2 资源准备 3 adk agent构建 3.1 新建adk_agent_tool_serial python包 3.2 编辑__init__.py文件 4 配置env 4.1 新建.env文件 4.2 编辑.env文件 5 agent逻辑实现 5.1 …

降本增效的新引擎:GEO如何提升企业营销ROI

在当前经济环境下&#xff0c;企业面临着前所未有的成本压力和效率挑战。深耕数字营销二十余年&#xff0c;我们见证了从传统广告到数字营销&#xff0c;再到如今生成式AI时代的每一次效率变革。在这个新阶段&#xff0c;生成式引擎优化&#xff08;GEO&#xff09;正在成为企业…

Blinko智能笔记系统实现跨平台同步与隐私保护的完整技术方案解析

文章目录 前言1. Docker Compose一键安装2. 简单使用演示3. 安装cpolar内网穿透4. 配置公网地址5. 配置固定公网地址 推荐 ​ 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。 点击跳转到网站 前言 是否…

OpenCV CUDA模块特征检测------创建Harris角点检测器的GPU实现接口cv::cuda::createHarrisCorner

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 该函数创建一个 基于 Harris 算法的角点响应计算对象&#xff0c;专门用于在 GPU 上进行高效计算。 它返回的是一个 cv::Ptrcv::cuda::Cornernes…

013旅游网站设计技术详解:打造一站式旅游服务平台

旅游网站设计技术详解&#xff1a;打造一站式旅游服务平台 在互联网与旅游业深度融合的时代&#xff0c;旅游网站成为人们规划行程、预订服务的重要工具。一个功能完备的旅游网站&#xff0c;通过用户管理、订单管理等核心模块&#xff0c;实现用户与管理员的高效交互。本文将…

Linux运维笔记:1010实验室电脑资源规范使用指南

文章目录 0. 检查资源使用情况&#xff0c;避免冲突检查在线用户检查 CPU 使用情况检查 GPU 使用情况协作建议 1. 备份重要文件和数据2. 定期清理硬盘空间3. 退出 ThinLinc 时注销&#xff0c;释放内存4. 校外使用时配置 VPN注意事项总结 实验室的电脑配备了 CPU 和 GPU 资源&a…

Nginx + Tomcat负载均衡群集

目录 一、案例环境 二、部署 Tomcat&#xff08;102/103&#xff09; 1、准备环境 &#xff08;1&#xff09;关闭firewalld 防火墙 &#xff08;2&#xff09;安装JDK 2、安装配置 Tomcat &#xff08;1&#xff09;Tomcat 的安装和配置 &#xff08;2&#xff09;移动…