memory model

时间:2023-05-01 17:24:29

最近看C++11 atomic发现对memory_order很是不理解,memory_order_relaxed/memory_order_consume/memory_order_acquire/memory_order_release/memory_order_acq_rel/

memory_order_seq_cst。这些都是跟memory model有关

关于memory model,对于线程来说,其实是跟编译器相关的。因为我们的编译器在把C++语言翻译成机器代码的时候,会进行各种优化。

我们做C++ GDB的时候,我们会发现,当我们使用-O2优化后,我们再调试的时候,发现程序的执行顺序根本就不是我们写的时候,我们想象的执行顺序。这样优化是有好处的,可以大大提高我们程序的运行速度,但是这样也不是都是好的(volatile类型不建议使用的原因,就是跟这个有关),这些优化都是建立在一个线程上进行的。所以在多线程的时候就要考虑优化造成的问题。

为了不让编译器在做优化的时候,不因为编译器的优化错误,而使程序错误,这就需要acquire/release原语。。

release时,编译器保证不会把写操作移到它后边,否则其他线程就看不到这个修改了;

acquire时,不会把其后的读操作移到它前面,否则读到的就是旧数据。

剩下的情况,编译器就可以*移动读写操作

而在C++11

memory_order_acquire

Acquire operation:

no reads in the current thread can be reordered before this load.This ensures that all writes in other threads that release the same atomic variable are visible in the current thread

在当前线程中,所有的read操作的乱序,不能出现在这个atomic变量load之前。 (意思就是在当前线程中,编译器或者cpu在优化代码的时候, 不能把读操作的代码出现在这个变量之前)这保证当前线程的writes是可以得到的,而且其他线程应该release这同一个atomic变量

memory_order_release:

Release operation:

no writes in the current thread can be reordered after this store. This ensures that all writes in the current thread are visible in other threads that acquire the same atomic variable.

在当前线程中所有的write不能被reorder到这个atomic变量之后,这保证当前线程的所有write是可以得到的,其他的线程的应该acquire这个atomic变量

memory_order_relaxed:

Relaxed ordering:

there are no constraints on reordering of memory accesses around the atomic variable.

    

在这个atomic变量上,关于reorder没有约束

memory_order_acq_rel

Acquire-release operation:

no reads in the current thread can be reordered before this load as well as no writes in the current thread can be reordered after this store.The operation is read-modify-write operation. It is ensured that all writes in another threads that release the same atomic variable are visible before the modification and the modification is visible in other threads that acquire the same atomic variable.

memory_order_scq_cst

Sequential ordering.

The operation has the same semantics as acquire-release operation, and additionally has sequentially-consistent operation ordering.

memory_order_consume

Consume operation:

no reads in the current thread dependent on the value currently loaded can be reordered before this load. This ensures that writes to dependent variables in other threads that release the same atomic variable are visible in the current thread. On most platforms, this affects compiler optimization only.

参考资料:

1 . 浅谈Memory Reordering

2. 透过LINUX内核看无锁编程

3. Why the "volatile" type class should not be used

4.锁的意义