當前位置: 首頁>>代碼示例 >>用法及示例精選 >>正文


Rust compiler_fence用法及代碼示例


本文簡要介紹rust語言中 Function core::sync::atomic::compiler_fence 的用法。

用法

pub fn compiler_fence(order: Ordering)

編譯器內存柵欄。

compiler_fence不發出任何機器代碼,但限製編譯器允許執行的內存重新排序類型。具體來說,取決於給定的Ordering語義上,編譯器可能被禁止將讀取或寫入從調用之前或之後移動到調用的另一端compiler_fence。請注意,它確實不是防止硬件從做這樣的重新排序。這在單線程執行上下文中不是問題,但是當其他線程可能同時修改內存時,需要更強的同步原語,例如core::sync::atomic::fence是必要的。

不同排序語義阻止的重新排序是:

  • 使用 SeqCst ,不允許在這一點上重新排序讀取和寫入。
  • 使用 Release ,之前的讀取和寫入不能移過後續的寫入。
  • 使用 Acquire ,後續的讀取和寫入不能移動到前麵的讀取之前。
  • 使用 AcqRel ,上述兩條規則都被強製執行。

compiler_fence通常僅用於防止線程爭用與它自己。也就是說,如果給定線程正在執行一段代碼,然後被中斷,並開始在其他地方執行代碼(同時仍然在同一線程中,並且概念上仍然在同一核心上)。在傳統程序中,這隻能在注冊信號處理程序時發生。在更底層的代碼中,處理中斷、實現具有搶占函數的綠色線程等時也會出現這種情況。鼓勵好奇的讀者閱讀 Linux 內核的討論 memory 障礙.

Panics

如果 order Relaxed 則會出現Panics。

例子

沒有compiler_fence, 這assert_eq!在下麵的代碼中是不是盡管一切都發生在單個線程中,但保證會成功。要了解原因,請記住編譯器可以自由地將存儲交換到IMPORTANT_VARIABLEIS_READY因為他們都是Ordering::Relaxed。如果是這樣,並且信號處理程序將在之後立即調用IS_READY更新後,信號處理程序將看到IS_READY=1, 但IMPORTANT_VARIABLE=0。用一個compiler_fence可以糾正這種情況。

use std::sync::atomic::{AtomicBool, AtomicUsize};
use std::sync::atomic::Ordering;
use std::sync::atomic::compiler_fence;

static IMPORTANT_VARIABLE: AtomicUsize = AtomicUsize::new(0);
static IS_READY: AtomicBool = AtomicBool::new(false);

fn main() {
    IMPORTANT_VARIABLE.store(42, Ordering::Relaxed);
    // prevent earlier writes from being moved beyond this point
    compiler_fence(Ordering::Release);
    IS_READY.store(true, Ordering::Relaxed);
}

fn signal_handler() {
    if IS_READY.load(Ordering::Relaxed) {
        assert_eq!(IMPORTANT_VARIABLE.load(Ordering::Relaxed), 42);
    }
}

相關用法


注:本文由純淨天空篩選整理自rust-lang.org大神的英文原創作品 Function core::sync::atomic::compiler_fence。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。