• 內存屏障

    編輯
    本詞條由“匿名用戶” 建檔。

    內存屏障

    編輯

    在計算中,內存屏障,也稱為 membar、內存柵欄或柵欄指令,是一種屏障指令,它會導致中央處理器 (CPU) 或編譯器對屏障前后發出的內存操作強制執行順序約束 操作說明。 這通常意味著在屏障之前發出的操作保證在屏障之后發出的操作之前執行。

    內存屏故障是必要的,因為大多數現代 CPU 都采用可能導致亂序執行的性能優化。 這種內存操作(加載和存儲)的重新排序通常在單個執行線程中不會引起注意,但除非仔細控制,否則可能會導致并發程序和設備驅動程序出現不可預測的行為。 排序約束的確切性質取決于硬件并由體系結構的內存排序模型定義。 一些架構為強制執行不同的排序約束提供了多個障礙。

    內存中斷通常用于實現在多個設備共享的內存上運行的低級機器代碼。 此類代碼包括多處理器系統上的同步原語和無鎖數據結構,以及與計算機硬件通信的設備驅動程序。

    例子

    編輯

    當程序在單 CPU 機器上運行時,硬件會執行必要的簿記,以確保程序執行時就好像所有內存操作都按照程序員指定的順序(程序順序)執行,因此內存屏障不是必需的。 但是,當內存與多個設備共享時,例如多處理器系統中的其他 CPU,或內存映射外設,亂序訪問可能會影響程序行為。 例如,第二個 CPU 可能會看到第一個 CPU 以不同于程序順序的順序進行內存更改。

    程序通過可以是多線程的進程運行(即軟件線程,如 pthreads,而不是硬件線程)。 不同的進程不共享內存空間,因此本討論不適用于兩個程序,每個程序都運行在不同的進程(因此不同的內存空間)。 它適用于在單個進程中運行的兩個或多個(軟件)線程(即單個內存空間,多個軟件線程共享單個內存空間)。 單個進程中的多個軟件線程可以在多核處理器上同時運行。

    以下在多核處理器上運行的多線程程序舉例說明了這種亂序執行如何影響程序行為:

    最初,內存位置 x 和 f 的值都為 0。在處理器 #1 上運行的軟件線程在 f 的值為零時循環,然后打印 x 的值。 在處理器#2 上運行的軟件線程將值 42 存儲到 x 中,然后將值 1 存儲到 f 中。 兩個程序片段的偽代碼如下所示。

    程序的步驟對應于單獨的處理器指令。

    線程 #1 核心 #1:

    而(f == 0); // 這里需要內存柵欄 print x;

    線程 #2 核心 #2:

    x = 42; // 這里需要內存柵欄 f = 1;

    人們可能期望 print 語句總是打印數字 42; 然而,如果線程 #2 的存儲操作是亂序執行的,則 f 有可能在 x 之前更新,因此打印語句可能會打印 0。類似地,線程 #1 的加載操作可能 亂序執行,并且有可能在檢查 f 之前讀取 x,因此 print 語句可能再次打印出意外的值。 對于大多數程序來說,這兩種情況都是不可接受的。 必須在線程#2 分配給 f 之前插入內存屏障,以確保 x 的新值在 f 值發生變化時或之前對其他處理器可見。 另一個要點是,還必須在線程#1 訪問 x 之前插入一個內存屏障,以確保在看到 f 的值發生變化之前不會讀取 x 的值。

    另一個例子是當驅動程序執行以下序列時:

    prepare data for a hardware module // 這里需要內存柵欄觸發硬件模塊處理數據

    內存屏障

    如果處理器的存儲操作亂序執行,則硬件模塊可能會在數據在內存中準備就緒之前被觸發。

    對于另一個說明性示例(在實際實踐中出現的一個不平凡的示例),請參閱雙重檢查鎖定。

    多線程編程和內存可見性

    編輯

    多線程程序通常使用高級編程環境(例如 Java 和 .NET Framework)或應用程序編程接口 (API)(例如 POSIX Threads 或 Windows API)提供的同步原語。 提供諸如互斥鎖和信號量之類的同步原語以同步從并行執行線程訪問資源。 這些原語通常使用提供預期內存可見性語義所需的內存屏障來實現。

    內容由匿名用戶提供,本內容不代表www.gelinmeiz.com立場,內容投訴舉報請聯系www.gelinmeiz.com客服。如若轉載,請注明出處:http://www.gelinmeiz.com/195957/

    (1)
    詞條目錄
    1. 內存屏障
    2. 例子
    3. 多線程編程和內存可見性

    輕觸這里

    關閉目錄

    目錄
    91麻精品国产91久久久久