面试二十七、 CAS和Atomic

CAS锁机制(无锁、自旋锁、乐观锁、轻量级锁)-CSDN博客

1. ABA问题

在C++中,可以使用std::atomic和版本号来解决ABA问题。C++标准库没有直接提供类似Java的AtomicStampedReference,但可以通过将版本号和指针组合在一起实现类似的效果。

#include <atomic>
#include <iostream>
#include <thread>template <typename T>
class AtomicStampedReference {
public:AtomicStampedReference(T initial_value, int initial_stamp): value_(initial_value), stamp_(initial_stamp) {}bool compare_and_set(T expected_value, T new_value, int expected_stamp, int new_stamp) {auto current_value = value_.load();auto current_stamp = stamp_.load();return (current_value == expected_value && current_stamp == expected_stamp) &&value_.compare_exchange_strong(current_value, new_value) &&stamp_.compare_exchange_strong(current_stamp, new_stamp);}T get_reference() const {return value_.load();}int get_stamp() const {return stamp_.load();}private:std::atomic<T> value_;std::atomic<int> stamp_;
};void aba_example() {AtomicStampedReference<int> atomicStampedRef(100, 0);auto thread1 = [&atomicStampedRef]() {int stamp = atomicStampedRef.get_stamp();int reference = atomicStampedRef.get_reference();std::cout << "Thread 1 initial stamp: " << stamp << "\n";std::cout << "Thread 1 initial value: " << reference << "\n";if (atomicStampedRef.compare_and_set(reference, reference + 1, stamp, stamp + 1)) {std::cout << "Thread 1 new stamp: " << atomicStampedRef.get_stamp() << "\n";std::cout << "Thread 1 new value: " << atomicStampedRef.get_reference() << "\n";}};auto thread2 = [&atomicStampedRef]() {int stamp = atomicStampedRef.get_stamp();int reference = atomicStampedRef.get_reference();atomicStampedRef.compare_and_set(reference, reference + 1, stamp, stamp + 1);atomicStampedRef.compare_and_set(reference + 1, reference, stamp + 1, stamp + 2);std::cout << "Thread 2 stamp after ABA: " << atomicStampedRef.get_stamp() << "\n";std::cout << "Thread 2 value after ABA: " << atomicStampedRef.get_reference() << "\n";};std::thread t1(thread1);std::thread t2(thread2);t1.join();t2.join();
}int main() {aba_example();return 0;
}

2. 自旋时间长开销大

循环时间长开销大

  • 描述:当多个线程竞争同一个CAS操作时,如果一直失败,线程会不断自旋重试,造成CPU资源的浪费。尤其在高并发情况下,频繁的CAS重试会导致较高的CPU开销。
  • 解决办法:可以使用自适应自旋锁或其他锁机制来减轻自旋的开销。

        自旋锁在高竞争情况下会导致大量CPU资源浪费。可以使用自适应自旋锁或结合其他锁机制来减轻这种开销。以下是一个简单的自适应自旋锁实现示例。

#include <atomic>
#include <thread>
#include <iostream>
#include <chrono>class AdaptiveSpinLock {
public:AdaptiveSpinLock() : flag(ATOMIC_FLAG_INIT) {}void lock() {int spin_count = 0;while (flag.test_and_set(std::memory_order_acquire)) {++spin_count;if (spin_count > max_spin_count) {std::this_thread::yield(); // 出让CPUspin_count = 0;}}}void unlock() {flag.clear(std::memory_order_release);}private:static const int max_spin_count = 1000; // 自适应阈值std::atomic_flag flag;
};void spinlock_example() {AdaptiveSpinLock lock;int counter = 0;auto increment = [&lock, &counter]() {for (int i = 0; i < 1000; ++i) {lock.lock();++counter;lock.unlock();}};std::thread t1(increment);std::thread t2(increment);t1.join();t2.join();std::cout << "Final counter value: " << counter << "\n";
}int main() {spinlock_example();return 0;
}

3. 多变量原子操作

CAS只能保证单个变量的原子操作,要保证多个变量的原子操作,可以使用锁机制。以下是使用std::mutex来保证多个变量的原子操作的示例。

#include <mutex>
#include <thread>
#include <iostream>class MultiVariable {
public:void update(int a, int b) {std::lock_guard<std::mutex> lock(mtx);var1 = a;var2 = b;}void get(int& a, int& b) {std::lock_guard<std::mutex> lock(mtx);a = var1;b = var2;}private:int var1 = 0;int var2 = 0;std::mutex mtx;
};void multivariable_example() {MultiVariable mv;auto writer = [&mv]() {for (int i = 0; i < 1000; ++i) {mv.update(i, i * 2);}};auto reader = [&mv]() {for (int i = 0; i < 1000; ++i) {int a, b;mv.get(a, b);std::cout << "Read values: " << a << ", " << b << "\n";}};std::thread t1(writer);std::thread t2(reader);t1.join();t2.join();
}int main() {multivariable_example();return 0;
}

4.CAS使用注意事项
(1)CAS需要和volatile配合使用

CAS只能保证变量的原子性,不能保证变量的内存可见性。CAS获取共享变量的值时,需要和volatile配合使用,来保证共享变量的可见性

(2)CAS适用于并发量不高、多核CPU的情况

CPU多核情况下可以同时执行,如果不合适就失败。而并发量过高,会导致自旋重试耗费大量的CPU资源。

5. volatile

  • C++中的volatile:主要用于防止编译器优化,确保每次访问变量时从内存中读取最新的值,但不保证多线程环境下的内存可见性和顺序一致性。
  • 内存可见性:在C++中使用std::atomic和内存序列来确保多线程环境下的内存可见性和顺序一致性。

5.atomic

【超详解】C++原子变量atomic,全面解密!_c++ atomic-CSDN博客

atomic的底层实现 - 王的博客 - 博客园 (cnblogs.com)

CPU多核同步原语 - 知乎 (zhihu.com)

深入解析现代C++中的原子(std::atomic)-51CTO.COM

std::atomic通过硬件提供的原子指令实现无锁的原子操作,确保在多线程环境下的数据一致性和线程安全。通过使用内存顺序,可以进一步控制操作的可见性和顺序,以满足不同的并发编程需求。

 

 

 

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

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

相关文章

ESP32-C3模组上跑通OTA升级(10)

接前一篇文章&#xff1a;ESP32-C3模组上跑通OTA升级&#xff08;9&#xff09; 八、程序调试过程中遇到的问题及解决 前边各篇文章主要讲解了OTA的基础知识以及示例代码&#xff0c;但这其实是&#xff08;远远&#xff09;不够的&#xff0c;真正要在ESP32-C3芯片上跑通&…

【并发程序设计】13.信号机制

13.信号机制 概念&#xff1a; 信号机制是Unix、类Unix以及其他POSIX兼容的操作系统中的一种进程间通讯方式&#xff0c;它允许进程在发生特定事件时接收通知。 信号机制是操作系统中的一个重要概念&#xff0c;它提供了一种异步的通知机制&#xff0c;用于在进程之间传递消…

docker-compose 配置大全,持续更新

docker-compose 配置 安装docker-compose 1、执行脚本 由于github下载速度很慢,我将用到的程序放到了gitee仓库。 sudo curl -L https://gitee.com/brother_maolin/transfer/raw/master/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose2、执行,给予可执行…

6.s081通关小结

6.s081通关小结 终于是完成6.s081的所有lab了&#xff0c;感慨万千。已经忘了第一次听说这个lab是在什么时候了&#xff0c;只是模模糊糊地感觉是大三。那时的我第一次找到了刷题之外的新方向。但囿于小镇做题家对计算机认识的滞后性&#xff0c;什么Linux、Ubuntu之类的新系统…

【Python】解决Python报错:IndexError: queue index out of range

&#x1f9d1; 博主简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…

【Unity Shader入门精要 第12章】屏幕后处理效果(二)

1. 卷积 在图像处理中&#xff0c;卷积操作就是使用一个卷积核对一张图像中的每个像素做一系列的操作。 卷积核通常是一个四方形网格结构&#xff0c;如2x2、3x3的方形区域&#xff0c;该区域内每个方格都有一个权重值。 当对图像中的某个像素进行卷积操作时&#xff0c;将卷…

Linux域名解析不了/网络不可达/虚拟机连接不了的问题

记录域名解析不了/网络不可达/虚拟机连接不了的问题问题 目录 文章目录 记录域名解析不了/网络不可达/虚拟机连接不了的问题问题1.首先确定已经连接上路由器(我的就是在这嗝屁了....)1.1 查看路由表1.2查看当前的网络连接状态&#xff0c;包括网关1.3查看网络接口的状态&…

如何解决研发数据传输层面安全可控、可追溯的共性需求?

研发数据在企业内部跨网文件交换&#xff0c;是相对较为普遍而频繁的文件流转需求&#xff0c;基于国家法律法规要求及自身安全管理需要&#xff0c;许多企业进行内部网络隔离。不同企业隔离方案各不相同&#xff0c;比如银行内部将网络隔离为生产网、办公网、DMZ区&#xff0c…

十四天学会Vue——Vue核心下篇(理论+实战)(第三天)

一、Vue核心下篇 1.15 常用的内置指令 1. v-text <!--准备好一个容器 --><div id"root"><!-- 1.v-text中的字符替换掉div整个字符 --><div v-text"name">你好,{{name}}</div><!-- 2.将标签当做字符串解析 --><di…

Vue Router (创建 挂载)

创建路由模块 在src目录下创建router.js文件作为模块&#xff0c;该文件中按照如下步骤进行操作 1.导入路由相关函数&#xff0c;具体代码如下&#xff1a; import{ createRouter&#xff0c;createWebHashHistory } from Vue-router在上述代码中&#xff0c;从Vue-router中…

网络原理-TCP/IP --应用层

T04BF &#x1f44b;专栏: 算法|JAVA|MySQL|C语言 &#x1faf5; 今天你敲代码了吗 目录 3.网络原理 -TCP/IP3.1 应用层 3.网络原理 -TCP/IP 3.1 应用层 应用层是程序员打交道最多的一层,与应用程序直接相关 而应用层的协议,实际上就规定了你写的程序,通过网络传输的时候,按…

2928. 给小朋友们分糖果 I

给你两个正整数 n 和 limit 。 请你将 n 颗糖果分给 3 位小朋友&#xff0c;确保没有任何小朋友得到超过 limit 颗糖果&#xff0c;请你返回满足此条件下的 总方案数 。 示例 1&#xff1a; 输入&#xff1a;n 5, limit 2 输出&#xff1a;3 解释&#xff1a;总共有 3 种方…

FX2N用什么编程软件:深入解析与选择指南

FX2N用什么编程软件&#xff1a;深入解析与选择指南 在工业自动化领域&#xff0c;FX2N系列PLC因其卓越的性能和广泛的应用而备受瞩目。然而&#xff0c;对于许多初学者和工程师来说&#xff0c;如何选择合适的编程软件来开发FX2N系列PLC却是一个令人困惑的问题。本文将从四个…

【LINUX】LINUX基础(目录结构、基本权限、基本命令)

文章目录 LINUX的目录结构LINUX的基本权限LINUX基本命令 LINUX的目录结构 /&#xff1a;表示根目录bin&#xff1a;存放二进制可执行文件(命令ls、cat、mkdir等)boot&#xff1a;存放系统引导文件dev&#xff1a;存放设备文件etc&#xff1a;存放系统配置文件home&#xff1a;…

LeeCode热题100(爬楼梯)

爬楼梯这个题我断断续续看了不下5遍&#xff0c;哪次看都是懵逼的&#xff0c;就会说是满足动态规划&#xff0c;满足斐波那契数列&#xff0c;也不说为什么。 本文一定让你明白怎么分析这个题的规律&#xff08;利用数学的递推思想来分析&#xff09;&#xff0c;看不懂来打我…

Ubuntu 22.04 .NET8 程序 环境安装和运行

前言 我们需要将.NET8编写的console控制台程序&#xff0c;部署在Ubuntu服务器上运行。 安装.NET运行时 1.增加微软包安装源 wget https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb sudo dpkg -i packages…

JAVA学习-练习试用Java实现“Z字形变换”

问题&#xff1a; 将一个给定字符串 s 根据给定的行数 numRows &#xff0c;以从上往下、从左到右进行 Z 字形排列。 比如输入字符串为 "PAYPALISHIRING" 行数为 3 时&#xff0c;排列如下&#xff1a; P A H N A P L S I I G Y I R 之后&#xff0c;你…

1114 全素日

你好哇&#xff0c;新的一天开始啦&#xff01; solution 取数值的不同部分&#xff0c;联想到借助string #include<iostream> #include<string> using namespace std; bool judge(string s){int n atoi(s.c_str());if(n 1 || n 0) return false;for(int i 2…

FT编程语言:探索其深度、广度与未来潜力

FT编程语言&#xff1a;探索其深度、广度与未来潜力 FT编程语言&#xff0c;作为一个新兴且充满潜力的编程领域&#xff0c;正逐渐引起开发者和研究者的广泛关注。其独特的设计理念和强大的功能使得它在多个方面展现出独特的魅力。本文将从四个方面、五个方面、六个方面和七个…

“浔川AI翻译”正式上线!——浔川AI社

1前言&#xff1a; 浔川AI翻译机是一种基于人工智能技术开发的翻译设备。它能够实时将一种语言的文本或口语翻译成另一种语言&#xff0c;使得不同语言之间的交流更加便捷。浔川AI翻译机利用深度学习算法和大数据训练模型&#xff0c;能够自动识别和理解输入的语言&#xff0c…