Memory 互斥可以取代内存屏障吗

Memory 互斥可以取代内存屏障吗,memory,linux-kernel,mutex,memory-barriers,Memory,Linux Kernel,Mutex,Memory Barriers,我试图理解记忆障碍,无意中发现了下面的维基百科链接 这很好地解释了这个概念,但也考虑到了在我们有mutex()锁定内存部分的系统中这是否真的有用 使用与维基百科中提到的相同的代码,下面的方法会使用互斥来解决问题吗 [注意:函数名并非特定于任何编程语言,只是为了简单起见] 处理器#1 处理器#2 内存条通常用于使具有无序能力的管道进入与其内存访问相关的定义良好的状态,因此与互斥体的概念正交,互斥体通常是多处理中更高级的概念(与CPU指令的无序执行无关)。 在编译器中使用优化时,决不能假设指令将以与

我试图理解记忆障碍,无意中发现了下面的维基百科链接 这很好地解释了这个概念,但也考虑到了在我们有mutex()锁定内存部分的系统中这是否真的有用

使用与维基百科中提到的相同的代码,下面的方法会使用互斥来解决问题吗

[注意:函数名并非特定于任何编程语言,只是为了简单起见]

处理器#1

处理器#2


内存条通常用于使具有无序能力的管道进入与其内存访问相关的定义良好的状态,因此与互斥体的概念正交,互斥体通常是多处理中更高级的概念(与CPU指令的无序执行无关)。 在编译器中使用优化时,决不能假设指令将以与中所写的完全相同的顺序执行 源代码。编译器可能会以这种方式重新排列汇编语言指令,以优化寄存器的使用方式。此外,现代CPU通常并行执行多条指令,并可能重新排序内存访问。这种重新排序可以大大加快程序的速度。 但可能导致意外的输出

因此,内存屏障原语确保编译器不会将与原语之前的C语句对应的汇编语言指令与与与原语之后的C语句对应的汇编语言指令混合。在linux中,barrier()宏是:

asm volatile("":::"memory")
解释如下:

  • asm指令告诉编译器插入汇编语言片段
  • volatile关键字禁止编译器使用程序的其他指令重新排列asm指令
  • memory关键字强制编译器假定RAM中的所有内存位置都已被汇编语言指令更改;因此,编译器无法使用asm指令之前存储在CPU寄存器中的内存位置值来优化代码

  • 内存屏障保证先前指令的所有可见效果在任何后续指令的可见效果之前变得可见。可能会重新排列观察到的效果顺序的事情有:

    • 编译器(通过对指令重新排序)
    • 故障管道
    • 具有宽松内存一致性的缓存系统(几乎都在现代系统上)
    互斥锁保证一次只有一个线程持有互斥锁

    这两个概念之间有一种关系:如果没有至少部分的内存屏障,互斥锁实际上是无用的。考虑这个例子:

    mutex_lock(a);
    x = x+1;
    mutex_unlock(a);
    
    锁定操作必须至少有一个“获取”屏障,以防止在获取锁定之前出现x负载。同样,“解锁”操作必须至少有一个“释放”屏障,以防止释放锁后出现x存储。也就是说,锁定-解锁对形成一个框架,操作无法从中逃脱。(尽管有时程序员会对重新排序导致操作爬行到框架中感到惊讶!)


    因此,锁定互斥锁并立即解锁互斥锁就像是一道内存屏障,尽管效率极低,因为它会强制串行执行。

    如果处理器1首先获得锁,该示例将死锁,因为这样一来,处理器1将永远旋转,而处理器2将无法获得锁。将C语言内联汇编的使用与Linux编程混为一谈不是一个好主意。
    asm volatile("":::"memory")
    
    mutex_lock(a);
    x = x+1;
    mutex_unlock(a);