简体   繁体   English

互斥锁可以取代内存障碍吗

[英]Can mutex replace memory barriers

I was trying to understand memory barrier and came across the below wikipedia link http://en.wikipedia.org/wiki/Memory_barrier This explain the concept well but had thoughts if this is really helpful in system where we have mutex() locking the memory section. 我试图理解内存障碍,并遇到了以下Wikipedia链接http://en.wikipedia.org/wiki/Memory_barrier这很好地解释了这一概念,但曾想过这对于在我们将Mutex()锁定内存部分。

Taking the same code as mentioned in wikipedia, will the below approach solve the problem using mutex? 采用与Wikipedia中所述相同的代码,以下方法是否可以使用互斥锁解决问题?

[Note: Function names are not specific to any programming language, just used for simplicity sake] [注意:函数名称并非特定于任何编程语言,只是为了简单起见而使用]

Processor #1 处理器#1

mutex_lock(a)
while (f == 0);
print x;
mutex_unlock(a)

Processor #2 处理器#2

mutex_lock(a)
x = 42;
f = 1;
mutex_unlock(a)

A memory barrier guarantees that all visible effects of prior instructions become observable before those of any subsequent instructions. 内存屏障保证了在先指令的所有可见效果都可以在任何后续指令之前看到。 Things that might reorder the observed order of effects are: 可能会重新排列观察到的效果顺序的事情是:

  • Compilers (by reordering instructions) 编译器(通过重新排序说明)
  • Out of order pipelines 管道混乱
  • Cache systems with relaxed memory consistency (practically all on modern systems) 具有轻松的内存一致性的高速缓存系统(实际上在现代系统上都是如此)

A mutex guarantees that only one thread holds the mutex at a time. 互斥锁可确保一次只有一个线程持有该互斥锁。

There is a relationship between the two concepts: a mutex is practically useless without at least partial memory barriers. 这两个概念之间存在关系:互斥锁实际上是没有用的,没有至少部分内存障碍。 Consider this example: 考虑以下示例:

mutex_lock(a);
x = x+1;
mutex_unlock(a);

The lock operation must have at least an "acquire" barrier that prevents the load of x from appearing to happen before the lock is acquired. 锁定操作必须至少具有一个“获取”屏障,以防止x的负载在获取锁定之前出现。 Likewise, the "unlock" operation must have at least a "release" barrier that prevents the store of x from appearing to happen after the lock is released. 同样,“解锁”操作必须至少具有“释放”屏障,以防止x的存储在释放锁定后出现。 That is the lock-unlock pair form a cage from which operations cannot escape. 就是说,锁-解锁对形成了一个笼子,操作无法逃脱。 (Though sometimes programmers are surprised when reordering causes operations to crawl into the cage!) (尽管有时程序员在重新排序时会感到惊讶,导致操作爬笼中!)

So locking a mutex and immediately unlocking it acts as a memory barrier, albeit a horribly inefficient one since it forces serial execution. 因此,锁定互斥锁并立即将其解锁会成为内存屏障,尽管效率极低,因为它会强制执行串行。

内存条通常用于使功能混乱的流水线相对于其内存访问进入定义良好的状态,因此与互斥量的概念正交,互斥量的概念通常在多处理中是更高得多的概念(与CPU指令的乱序执行无关)。

Mutex and other lock in kernel uses the barrier internally to ensure that code runs in the exact order as expected. 互斥锁和内核中的其他锁在内部使用该屏障,以确保代码按预期的正确顺序运行。 When using optimization in compliers, You should never assume that instructions will be performed in the exact same order as written in the source code. 在编译器中使用优化时,您永远不应假定将按照与源代码中编写的顺序完全相同的顺序执行指令。 Compiler might reorder the assembly language instructions in such a way to optimize how registers are used. 编译器可能会以优化寄存器使用方式的方式对汇编语言指令进行重新排序。 Moreover, modern CPUs usually execute several instructions in parallel and might reorder memory accesses. 此外,现代CPU通常并行执行几条指令,并且可能会重新排序内存访问。 These kinds of reordering can greatly speed up the program. 这些重新排序可以大大加快程序的速度。 But can result into unexpected output! 但是会导致意外的输出!

Hence MEMORY BARRIER primitive ensures that the assembly language instructions corresponding to C statements placed before the primitive are not mixed by the compiler with assembly language instructions corresponding to C statements placed after the primitive. 因此,MEMORY BARRIER原语可确保与放置在原语之前的C语句相对应的汇编语言指令不会被编译器与对应于在原语之后的C语句所对应的汇编语言指令混合。 In linux barrier() macro is: 在linux barrier()中,宏为:

asm volatile("":::"memory")

Here is the explanation: 这里是解释:

  1. asm instruction tells the compiler to insert an assembly language fragment asm指令告诉编译器插入汇编语言片段
  2. volatile keyword forbids the compiler to reshuffle the asm instruction with the other instructions of the program volatile关键字禁止编译器将asm指令与程序的其他指令重新组合
  3. The memory keyword forces the compiler to assume that all memory locations in RAM have been changed by the assembly language instruction; memory关键字强制编译器假定RAM中的所有内存位置都已被汇编语言指令更改; therefore, the compiler cannot optimize the code by using the values of memory locations stored in CPU registers before the asm instruction 因此,编译器无法通过在asm指令之前使用存储在CPU寄存器中的内存位置的值来优化代码

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM