内存模型与同步原语 - 3 x86 内存模型

简介: x86-TSO (Total Store Ordering) 是论文 *x86-TSO: A Rigorous and Usable Programmer’s Model for x86 Multiprocessors* 提出的一种 memory model,这是论文作者根据 Intel/AMD specification 的阅读总结,提出的一种总结性的内存模型 虽然 Intel/AMD 官

x86-TSO (Total Store Ordering) 是论文 x86-TSO: A Rigorous and Usable Programmer’s Model for x86 Multiprocessors 提出的一种 memory model,这是论文作者根据 Intel/AMD specification 的阅读总结,提出的一种总结性的内存模型

虽然 Intel/AMD 官方一开始并不是按照这个模型进行架构设计的,但是当前这个模型可以比较好地描述 x86 架构下的 memory model,因而这个模型对于理解 x86 memory model 具有重要作用

15986017943920.jpg

x86-TSO 模型中存在 store buffer 但不存在 invalidate queue,同时模型可以简要归纳为以下四点

  • The store buffers are FIFO and a reading thread must read its most recent buffered write, if there is one, to that address; otherwise reads are satisfied from shared memory.
  • An MFENCE instruction flushes the store buffer of that thread.
  • To execute a LOCK’d instruction, a thread must first obtain the global lock. At the end of the instruction, it flushes its store buffer and relinquishes the lock. While the lock is held by one thread, no other thread can read.
  • A buffered write from a thread can propagate to the shared memory at any time except when some other thread holds the lock.

x86-TSO: A Rigorous and Usable Programmer’s Model for x86 Multiprocessors

memory order

x86 架构下只可能存在 StoreLoad reorder,但是只限于对不同内存地址的操作

  • Reads are not reordered with other reads.

  • Writes are not reordered with older reads.

  • Writes to memory are not reordered with other writes.

  • Reads may be reordered with older writes to different locations but not with older writes to the same location.

  • Reads may be reordered with older writes to the same location in case of Intra-Processor Forwarding.

Intel Architecture Software Developer Manual, volume 3A, chapter 8, section 8.2 "Memory Ordering"

首先,x86 架构下不存在 invalidate queue,因而也就不存在 LoadLoad reorder

其次 x86 架构下存在 store buffer,store buffer 有可能导致 StoreStore/StoreLoad reorder,但是 x86 架构下 single-CPU 上的多条 write 指令之间不会发生重排,即使这些 write 指令的是不同的内存地址,因而 x86 架构下不存在 StoreStore reorder

而由于 store buffer 的存在,x86 架构下是存在 StoreLoad reorder 的,但是也只限于对不同内存地址的操作,也就是说对同一内存地址的 Store/Load 指令是不会发生 reorder 的

CPU barrier

x86 架构下只存在 StoreLoad reorder,以下方法都可以用于 x86 架构下的 CPU barrier

  • LOCK instruction
  • SFENCE/LFENCE/MFENCE

LOCK instruction

LOCK 指令可以用于 x86 架构下的 CPU barrier

LOCK 指令最初用于实现 atomic RMW (Read-Modify-Write) 操作,但是 LOCK 指令执行的时候也会作 flush store buffer 操作

Locking operations typically operate like I/O operations in that they wait for all previous instructions to complete and for all buffered writes to drain to memory.

Intel Architecture Software Developer Manual, volume 3A, chapter 8, section 8.2 "Memory Ordering"

因而 load/store 操作都不能与 LOCK 指令发生重排,也就是说 LOCK 指令相当于一个 full barrier,因而可以用于消除 StoreLoad reorder

Reads or writes cannot be reordered with I/O instructions, locked instructions, or serializing instructions.

Intel Architecture Software Developer Manual, volume 3A, chapter 8, section 8.2 "Memory Ordering"

FENCE

此外 x86 架构下专门的 FENCE 指令也可用于 CPU barrier

MFENCE 指令相当于一个 full barrier,load/store 操作都不能与其发生重排

MFENCE 指令执行时会执行 flush store buffer 操作,此时会等待 store buffer 中的所有 invalidate message 都收到对应的 invalidate acknowledge message 时,才能继续执行 MFENCE 指令之后的内存访问指令,从而消除 StoreLoad reorder

all memory operantions stay above the line
---------------------
       MFENCE
---------------------
all memory operantions stay below the line

LFENCE/SFENCE 指令则相当于是更加细粒度的 barrier

LFENCE 指令相当于一个 read barrier,前后的 load 指令都不能与 LFENCE 指令发生重排,此外 LFENCE 指令也不能与之后的 STORE 指令发生重排

all LOADs stay above the line
---------------------
       LFENCE
---------------------
all LOADs/STOREs stay below the line

SFENCE 指令则相当于一个 write barrier,前后的 store 指令都不能与 SFENCE 指令发生重排

all STOREs stay above the line
---------------------
       SFENCE
---------------------
all STOREs stay below the line

SFENCE — Serializes all store (write) operations that occurred prior to the SFENCE instruction in the program instruction stream, but does not affect load operations.
LFENCE — Serializes all load (read) operations that occurred prior to the LFENCE instruction in the program
MFENCE — Serializes all store and load operations that occurred prior to the MFENCE instruction in the program instruction stream.

Intel Architecture Software Developer Manual, volume 3A, chapter 8, section 8.2 "Memory Ordering"

Reads cannot pass earlier LFENCE and MFENCE instructions.
Writes and executions of CLFLUSH and CLFLUSHOPT cannot pass earlier LFENCE, SFENCE, and MFENCE instructions.
LFENCE instructions cannot pass earlier reads.
SFENCE instructions cannot pass earlier writes or executions of CLFLUSH and CLFLUSHOPT.
MFENCE instructions cannot pass earlier reads, writes, or executions of CLFLUSH and CLFLUSHOPT.

Intel Architecture Software Developer Manual, volume 3A, chapter 8, section 8.2 "Memory Ordering"

相关文章
|
9天前
|
缓存 算法 Java
本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制
在现代软件开发中,性能优化至关重要。本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制。通过调整垃圾回收器参数、优化堆大小与布局、使用对象池和缓存技术,开发者可显著提升应用性能和稳定性。
30 6
|
3月前
|
NoSQL 关系型数据库 MySQL
实时计算 Flink版产品使用问题之全量同步的内存释放该怎么实现
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
3月前
|
SQL 存储 关系型数据库
实时计算 Flink版产品使用问题之同步MySQL多张表的过程中,内存释放依赖于什么
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
4月前
|
设计模式 安全 Java
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
78 1
|
4月前
|
设计模式 安全 Java
Java面试题:请解释Java中的线程池以及为什么要使用线程池?请解释Java中的内存模型以及如何避免内存泄漏?请解释Java中的并发工具包以及如何实现一个简单的线程安全队列?
Java面试题:请解释Java中的线程池以及为什么要使用线程池?请解释Java中的内存模型以及如何避免内存泄漏?请解释Java中的并发工具包以及如何实现一个简单的线程安全队列?
44 1
|
4月前
|
存储 算法 Java
JAVA内存模型与JVM内存模型的区别
JAVA内存模型与JVM内存模型的区别
|
4月前
|
存储 设计模式 监控
Java面试题:如何在不牺牲性能的前提下,实现一个线程安全的单例模式?如何在生产者-消费者模式中平衡生产和消费的速度?Java内存模型规定了变量在内存中的存储和线程间的交互规则
Java面试题:如何在不牺牲性能的前提下,实现一个线程安全的单例模式?如何在生产者-消费者模式中平衡生产和消费的速度?Java内存模型规定了变量在内存中的存储和线程间的交互规则
48 0
|
4月前
|
设计模式 存储 缓存
Java面试题:结合单例模式与Java内存模型,设计一个线程安全的单例类?使用内存屏障与Java并发工具类,实现一个高效的并发缓存系统?结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
Java面试题:结合单例模式与Java内存模型,设计一个线程安全的单例类?使用内存屏障与Java并发工具类,实现一个高效的并发缓存系统?结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
38 0
|
3月前
|
存储 编译器 C语言
【C语言篇】数据在内存中的存储(超详细)
浮点数就采⽤下⾯的规则表⽰,即指数E的真实值加上127(或1023),再将有效数字M去掉整数部分的1。
370 0
|
22天前
|
存储 C语言
数据在内存中的存储方式
本文介绍了计算机中整数和浮点数的存储方式,包括整数的原码、反码、补码,以及浮点数的IEEE754标准存储格式。同时,探讨了大小端字节序的概念及其判断方法,通过实例代码展示了这些概念的实际应用。
46 1