簡介記憶體模型與C 11的memory order

2021-10-22 12:23:38 字數 2359 閱讀 3735

先看一段**

#include

#include

int a =0;

int b =0;

void

func1()

void

func2()

intmain

(void

)

再看一段彙編**:

1: load    reg3, 1      ;將立即數1放入暫存器reg3

2: move reg4,reg3 ;將reg3的資料放入reg4

3: store reg4, a ;將reg4的資料存入記憶體位址a

4: load reg5, 2 ;將立即數2放入暫存器reg5

5: store reg5, b ;將reg5的資料存入記憶體位址b

以上的偽彙編**代表了temp = 1; a = temp; b = 2;

通常情況下指令都是按照1~5的順序執行,這種記憶體模型稱為強順序(strong ordered)。

不過可以看到,指令1、2、3和指令4、5的執行順序不影響結果。

有一些處理器可能會將指令的順序打亂,例如按照1-4-2-5-3的順序執行,這種記憶體模型稱為弱順序(weak ordered).

如果乙個平台是弱順序記憶體模型,那麼上文列印a,b的**中,執行緒func2就有可能列印出0,2的結果。

既然弱順序記憶體模型可能會導致程式問題,為什麼有些平台會使用這種模型?

簡單的說,這種模型能讓處理器有更好的並行性,提高指令執行的效率。

為了保證指令的順序執行,需要在彙編指令中加入一條記憶體柵欄指令(memory barrier)

它能保證指令的順序執行,但是會影響處理器效能。

c++11中的原子操作還可以包含乙個引數:記憶體順序(memory_order)

memory_order 是c++11為原子型別定義的記憶體模型,以便靈活地控制原子型別的執行順序。

**通常情況下,使用該引數將有利於編譯器進一步提高並行效能。**如下:

atomic<

int>a(

0);atomic<

int>b(

0);void

func1()

上面的**使用了store函式進行賦值。store函式有2個引數,第乙個是要寫入的值,第二個是名為memory_order的列舉值。

這裡使用了std::memory_order_relaxed,表示鬆散記憶體順序,該列舉值代表可以任由編譯器重新排序或則由處理器亂序處理

這樣a和b的賦值執行順序性就被解除了。

在c++11中一共有 6種 memory_order列舉值,預設按照memory_order_seq_cst執行:

列舉值含義

memory_order_relaxed

不對執行順序做任何保障

memory_order_acquire

本執行緒中,所有後續的讀操作均在本條原子操作完成後執行

memory_order_release

本執行緒中,所有之前的寫操作完成後才能執行本條原子操作

memory_order_acq_rel

同時包含memory_order_acquire和memory_order_release標記

memory_order_consume

本執行緒中,所有後續的有關本原子型別的操作,必須在本條原子操作完成後執行

memory_order_seq_cst

全部訪問都按順序執行

注意: 不是所有的memory_order都能被atomic成員使用:

原子型別提供的一些操作符,比如operator=operator+=等函式,都是以memory_order_seq_cst為實參的原子操作封裝,所以他們都是順序一致性的。

如果要指定記憶體順序的話,則應該採用storeloadatomic_fetch_add這樣的函式。

最後說明一下,std::atomic和std::memory_order只有在多執行緒無鎖程式設計時才會用到。在x86_64平台,由於是強順序記憶體模型的,為了保險起見,不要使用std::memory_order,使用std::atmoic預設形式即可,因為std::atmoic預設是強順序記憶體模型。

C 11記憶體模型

一 幾種同步關係 1.執行緒內部的資料關係 1.1 sequenced before 這是表示式與表示式之間的一種配對的不對稱的關係,僅用於同乙個執行緒內。實際執行順序不能破壞語句間sequenced before的關係。1 的1.9.13 1.2 carries a dependency to 僅...

c 11 記憶體模型解讀

說到記憶體模型,首先需要明確乙個普遍存在,但卻未必人人都注意到的事實 程式通常並不是總按著照原始碼中的順序一一執行,此謂之亂序,亂序產生的原因可能有好幾種 編譯器出於優化的目的,在編譯階段將原始碼的順序進行交換。程式執行期間,指令流水被 cpu 亂序執行。inherent cache 的分層及重新整...

C 11 多工記憶體模型

記憶體模型 一般來說,記憶體模型可以分為靜態記憶體模型和動態記憶體模型 c 11的記憶體模型 std memory order就是c 11的記憶體模型。c 11為std atomic提供的memory order enum class memory order 雖然列舉定義了6個,但它們表示的是4種...