当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


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。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。