无锁编程——从CPU缓存一致性讲到内存模型(1)

一.前言

1.什么是有锁编程,什么是无锁编程?

在编程中,特别是在并发编程的上下文中,“无锁”和“有锁”是描述线程同步和资源访问控制的两种不同策略。

有锁(Locked):
有锁编程是指使用锁(例如互斥锁、信号量等)来控制对共享资源的访问。在有锁策略中,线程必须在执行关键部分的代码前获得锁,以确保同一时间只有一个线程可以访问和修改共享资源。当线程完成对共享资源的操作后,它释放锁,使得其他线程可以接着访问资源。

特点包括:

线程安全:通过锁可以防止多个线程同时访问共享资源,避免竞争条件。
阻塞:线程在尝试获取一个已被其他线程持有的锁时,将会被阻塞,直到锁被释放。
开销:锁的获取和释放涉及操作系统层面的上下文切换,可能会导致较大的性能开销。
死锁:不正确的锁使用可能导致死锁,即两个或多个线程永久性地阻塞,等待彼此释放锁。

无锁(Lock-free):
无锁编程是一种不依赖于传统锁机制来控制共享资源访问的并发编程技术。无锁编程通常利用原子操作来确保即使在多个线程同时访问时,共享资源也能保持一致性。
那什么原子操作?

原子操作是指不可被中断的一个或一系列操作。它通过硬件支持来保证操作的原子性,通常使用特殊的CPU指令来实现。这些指令能够在单个步骤中完成读取-修改-写入的操作,而不会被其他线程中断。

上面提到的特殊指令->能够完成读取-修改-写入操作,指的是CAS(比较后交换技术)。为什么提到它,有什么用处?

这就要说到现代计算机的存储结构以及解决提升效率带来的一些硬件设备。


二.理解无锁编程需要的知识

1.存储结构

图片

可以看出L1和L2是每个核心都会有的。L3是一个处理器下的核心共有的。

主存(常规语境下所指的内存)是所有核心共有的。

越往下容量越大,同时读取速度越慢。

Cpu访问缓存的时候会有一个最小的读取单位,叫做cache line,一般是64个字节。

那么问题来了。为什么需要cache line ?(缓存),为什么这么设计?

因为:减少内存访问延迟:CPU的运行速度远远高于主内存的访问速度。Cache Line通过提供一个小而快速的存储,使得CPU能够更快地访问经常使用的数据和指令,从而减少了因等待内存访问而造成的延迟。

提高数据访问效率:由于数据访问通常具有空间局部性(连续的数据被一起访问),Cache Line作为一个数据块单位,可以一次性将多个连续的数据加载到缓存中。这样,当CPU访问其中一个数据时,很可能接下来的数据已经在缓存中了,从而提高了数据访问的效率。

带宽优化:与内存接口相比,CPU和缓存之间的数据带宽要宽得多。通过Cache Line,可以更有效地利用这带宽,因为每次传输都是传输一个数据块,而不是单个字节。

实现预取和并行处理:现代CPU通常具有预取机制,能够预测哪些数据将会被访问,并提前将数据加载到Cache中。Cache Line作为一个块单位,使得预取更加有效。同时,多核CPU可以利用Cache Line来并行处理数据,提高多任务处理的效率。

减少总线压力:如果没有缓存,CPU每次读写数据都要直接与内存通信,这会极大地增加总线上的数据流量。Cache Line允许CPU在大多数情况下与缓存而不是内存进行通信,从而减少了总线的压力。

提升能效:由于Cache Line减少了内存访问次数,因此也降低了内存功耗,整体上提升了系统的能效。

这种由cpu写到缓存而不是内存的策略叫做写回策略

三.写回策略

写直达策略:每次写操作会写到缓存中,也会写到内存中。写性能会很低,现代计算机很少使用了。

写回策略:尽量把数据存储到缓存之中,如果能写到缓存之中就避免写道内存中。

图片

 

是否命中缓存:是指之前的缓存中是否存有这个变量。

脏数据:缓存与内存不一致,或缓存有内存无的数据被标记为脏数据。

写数据的时候如果没有命中缓存,就利用LRU策略寻找到缓存中使用最少的区域,如果这块区域有数据并且是脏数据,那么将这块区域的数据刷入内存中。如果不是直接写入缓存。

读数据的时候如果没有命中缓存,先把数据从内存读入缓存,cpu再进行使用数据。

 

写回策略带来什么问题?

现代计算机结构有多个核心对应多个缓存,核心间共享的变量在不同的核心的缓存里内容不一样的问题。

如何解决?

四.MESI一致性协议

通过实现MESI一致性协议解决。他的内容及流程如下:

缓存一致性协议是确保多处理器系统中各个处理器的缓存数据一致性的机制。让我们详细讨论一下最常见的MESI(Modified, Exclusive, Shared, Invalid)协议的操作流程:

1. MESI协议状态:
   - Modified (M): 数据被修改,只在当前缓存中有效,与主存不一致。
   - Exclusive (E): 数据只在当前缓存中,未被修改,与主存一致。
   - Shared (S): 数据可能在多个缓存中存在,与主存一致。
   - Invalid (I): 缓存行无效。

2. 基本操作流程:

   a. 读操作:
      - 缓存未命中时:
        * 如果其他缓存有此数据(M或E状态),该缓存需先将数据写回主存。
        * 从主存读取数据,标记为S状态(如果其他缓存也有)或E状态(如果独占)。
      - 缓存命中时:
        * 如果是M、E或S状态,直接读取。
        * 如果是I状态,按缓存未命中处理。

   b. 写操作:
      - 缓存未命中时:
        * 如果其他缓存有此数据,需先使其无效。
        * 从主存读取数据,进行修改,标记为M状态。
      - 缓存命中时:
        * 如果是M状态,直接写入。
        * 如果是E状态,修改并变为M状态。
        * 如果是S状态,需先使其他缓存中的副本无效,然后修改并变为M状态。
        * 如果是I状态,按缓存未命中处理。

3. 状态转换:
   - I → E: 读取未被其他缓存持有的数据。
   - I → S: 读取被其他缓存共享的数据。
   - E → M: 修改独占的数据。
   - S → M: 修改共享的数据(需先使其他缓存副本无效)。
   - M → I, E → I, S → I: 其他处理器写入该数据。

4. 总线操作:
   - Read: 请求读取数据。
   - Read with Intent to Modify (RWITM): 请求读取并修改数据。
   - Invalidate: 使其他缓存中的副本无效。
   - Writeback: 将修改后的数据写回主存。

5. 协议执行流程:
   a. 处理器发出内存访问请求。
   b. 检查本地缓存状态。
   c. 根据状态和操作类型,可能需要发起总线事务。
   d. 其他处理器监听总线,根据需要更新自己的缓存状态。
   e. 完成数据访问或修改。

上面我们提到了CAS,与缓存一致性的关系?

五.CAS

CAS:是实现原子操作和无锁数据结构的基础。

function CAS(M, A, B) is
    if M == A
        M ← B
        return true
    else
        return false

它是一种原子操作,它比较内存位置的内容与给定值,只有在相同的情况下,才会将该内存位置的内容修改为新的给定值。

CAS与缓存一致性的关系就是需要CAS在写回策略的环境中维护正确性和高效性,这需要硬件层面的支持和软件的安全编程。

六.内存序和内存屏障

C++中原子操作往往有一个参数是规定内存序,用于指导编译器进行优化,用于指导cpu进行指令重排。可以解决两个问题,一是变量更新是否能马上被其他线程看到,二是代码顺序性的问题。

那么问题来了,为什么会有内存序问题?

因为编译器和cpu会在判断代码顺序不影响程序的情况下,有可能会重排相邻的代码执行顺序。比如一个线程锁住了一块内存空间,另一个线程无法操作那块内存空间,这项操作之后的操作并不刚需这块内存空间,这时候可能会重排先往后执行。这是为了提升整个系统的性能,但有时我们要求一定要按某个顺序执行,那么就有时候就不允许重排操作。

内存序和内存屏障是为了解决现代计算机系统中由于硬件优化和多核处理器引起的内存访问复杂性问题

内存序:指定了内存操作的可见性和顺序性规则。

内存屏障:用于强制执行特定的内存操作顺序的硬件指令。

内存序和内存屏障的关系
   - 内存序是高级抽象,定义了操作的语义。
   - 内存屏障是底层实现机制,用于实现内存序。

 C++11原子变量内存序的相关参数

见:std::memory_order - cppreference.com std内存屏障API,

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于JSP技术的校园餐厅管理系统

开头语: 你好呀,我是计算机学长猫哥!如果您对校园餐厅管理系统感兴趣或有相关需求,欢迎随时联系我。我的联系方式在文末,期待与您交流! 开发语言:Java 数据库:MySQL 技术&#x…

MySQL 8 命令安装卸载教程

一、下载MySQL8 下载连接 MySQL :: Download MySQL Community Server 我下载的是当前最新版8.4 二、安装 1.解压 解压到需要安装的位置,例如我的位置: 2.创建配置文件 新建文本文档,复制下面配置文件(注意修改路经)…

Cesium大屏-vue3注册全局组件

1.需求 说明:产品经理要求开发人员在地图大屏上面随意放置组件,并且需要通过数据库更改其组件大小,位置等;适用于大屏组件中场站视角、任意位置标题等。 2.实现 2.1GlobalComponents.vue 说明:containerList可以通…

javascript 常见设计模式

什么是设计模式? 在软件开发中,设计模式是解决特定问题的经验总结和可复用的解决方案。设计模式可以提高代码的复用性、可维护性和可读性,是提高开发效率的重要手段。 单例模式 1.概念 单例模式 (Singleton Pattern)&#xf…

ssm校园二手交易平台小程序

设计技术: 开发语言:Java数据库:MySQL技术:SpringMybatisSpringMvc微信小程序 工具:IDEA、Maven、Navicat 主要功能: (a) 管理员;管理员进入系统主要功能包括首页,个人中心&…

RedHat9 | 内部YUM本地源服务器搭建

服务器参数 标识公司内部YUM服务器主机名yum-server网络信息192.168.37.1/24网络属性静态地址主要操作用户root 一、基础环境信息配置 修改主机名 [rootyum-server ~]# hostnamectl hostname yum-server添加网络信息 [rootyum-server ~]# nmcli connection modify ens160 …

红黑树模拟

1.红黑树概念 红黑树,是一种二叉搜索树,但每个节点上增加了一个存储位表示结点的颜色,可以是RED或BLACK。通过任何一条根到叶子节点的途径上各个节点的着色方式的限制,红黑树确保没有一条路径会超过其他路径的二倍,因…

MySQL InnoDB Cluster 高可用集群部署

MySQL InnoDB Cluster 简介 官方文档:https://dev.mysql.com/doc/refman/8.4/en/mysql-innodb-cluster-introduction.html 本章介绍 MySQL InnoDB Cluster,它结合了 MySQL 技术,使您能够部署和管理完整的 MySQL 集成高可用性解决方案。 说…

SOC模块LoRa-STM32WLE5有哪些值得关注

SoC 是片上系统的缩写,是一种集成芯片,集成了计算机或其他电子系统的所有或大部分组件。这些组件通常包括中央处理器 (CPU)、内存、输入/输出接口和辅助存储接口。包含数字、模拟、混合信号和通常的 RF 信号处理功能,具体取决于应用。片上系统…

优质快刊合集!内含TOP刊、CCF推荐期刊!编辑友好,极速发表!

【SciencePub学术】本期给大家推荐的是几本计算机快刊合集,内含优质TOP刊,现在版面已经所剩不多。且均属于我处目前进展很顺的期刊,大家可以放心投稿! 计算机工程类 SCI(TOP刊 / CCF-C类) 【期刊简介】IF…

高斯过程的数学理解

目录 一、说明 二、初步:多元高斯分布 三、 线性回归模型与维度的诅咒 四、高斯过程的数学背景 五、高斯过程的应用:高斯过程回归 5.1 如何拟合和推理高斯过程模型 5.2 示例:一维数据的高斯过程模型 5.3 示例:多维数据的高斯过程模…

滑动窗口算法系列|基础概念|例题讲解

大家好,我是LvZi,今天带来滑动窗口算法系列|基础概念|例题讲解 一.滑动窗口问题基础概念 滑动窗口本质上是同向双指针问题,脱胎于双指针.使用两个指针l, r维护一定长度的数组区间,在r 指针遍历的过程中,执行进窗口,判断,更新结果,出窗口 等操作,当r指针遍历完毕,就能得到最后…

Study--Oracle-05-Oracler体系结构

一、oracle 体系概览 Oracle数据库的体系结构通常包括以下主要组件: 1、实例(Instance):运行数据库的软件环境,包括内存结构(SGA)和进程结构(Background Processes and User Proces…

如何一键修复0x0000011b错误,修复0x0000011b终极指南

在使用Windows操作系统和网络打印机的过程中,很多用户可能遇到了一个常见的错误代码“0x0000011b”。这个问题通常发生在尝试连接或使用网络打印机时,尤其是在安装了特定Windows安全更新后。本文将详细介绍如何快速一键修复此问题,确保您的打…

利用MMDetection将单阶段检测器作为Faster R-CNN的RPN

将单阶段检测器作为RPN 一、在 Faster R-CNN 中使用 FCOSHead 作为 RPNHead与原始配置的对比结果Neck (FPN)RPN HeadROI Head学习率 使用单阶段检测器作为RPN的优势1. 速度提升2. 准确性3. 简化架构4. 灵活性 二、评估候选区域三、用预先训练的 FCOS 训练定制的 Faster R-CNN 本…

开源模型应用落地-FastAPI-助力模型交互-WebSocket篇(五)

一、前言 使用 FastAPI 可以帮助我们更简单高效地部署 AI 交互业务。FastAPI 提供了快速构建 API 的能力,开发者可以轻松地定义模型需要的输入和输出格式,并编写好相应的业务逻辑。 FastAPI 的异步高性能架构,可以有效支持大量并发的预测请求,为用户提供流畅的交互体验。此外,F…

shellhub 部署

1、环境介绍 操作系统:龙蜥os 7.9 2、安装docker yum install -y yum-utils device-mapper-persistent-data lvm2 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo sed -i sdownload.docker.commirrors.aliyun.c…

江协科技51单片机学习- p23 DS1302实时时钟

🚀write in front🚀 🔎大家好,我是黄桃罐头,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流 🎁欢迎各位→点赞👍 收藏⭐️ 留言📝​…

【TB作品】智能台灯,ATMEGA16单片机,Proteus仿真

智能台灯 1 adc检测光强光敏电阻 显示电压 2 光强太高 也就是高于临界值 就关闭小灯 3 光强太低 也就是低于临界值 就打开小灯 3 按键修改临界值 显示 实验报告:基于ATMEGA16单片机的智能台灯设计与Proteus仿真 1. 实验背景 智能台灯是一种能够根据环境光强自动调…

计算机网络-第5章运输层

5.1运输层协议概述 5.1.1进程之间的通信 运输层向它上面的应用层提供通信服务,它属于面向通信部分的最高层,同时也是用户功能中的最低层。 通信的两端应当是两个主机中的应用进程。 运输层复用和分用:复用指在发送方不同的应用进程都可以…