C&C++   发布时间:2022-04-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了以轻松的顺序读共享变量:理论上有可能吗?有可能在C吗?大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
虑以下伪@L_673_0@:
expected = null;
if (variable == expected)
{
    atomic_compare_exchange_strong(
        &variable,expected,desired(),memory_order_acq_rel,memory_order_acq);
}
return variable;

观察当执行变量==期望检查时,没有“获取”语义.

在我看来,希望将至少被称为一次,每次最多一次.
此外,如果需要,从不返回null,则此@L_673_0@将永远不会返回null.

现在我有三个问题:

>以上是否正确?即,即使在每次阅读时都没有栅栏,我们也可以很好地阅读共享变量吗?
>可以在C中实现吗?如果是这样,怎么办?如果没有,为什么?
(希望有理由,不仅仅是因为标准这样说)
>如果(2)的答案为是,那么也可以在C中实现这一点,而不需要变量==期望执行变量的原子读取?

基本上,我的目标是要明白,一旦@L_673_0@已被每个线程至少执行一次,那么可以以一种与非共享变量性能相同的方式执行共享变量的延迟初始化?

(这有点是一个“语言律师”的问题,所以这意味着问题不在于这是一个好的还是有用的想法,而是在技术上是否可以正确地做到这一点.

解决方法

关于是否可以在C中执行共享变量的延迟初始化的问题,它具有与非共享变量性能(几乎)相同的性能

答案是,它取决于硬件架构,以及编译器和运行时环境的实现.至少在一些环境中是可能的.特别是在x86与GCC和Clang.

在x86上,可以在没有内存栅栏的情况下实现原子读取.基本上,原子阅读与非原子阅读相同.看看下面的编译单元:

std::atomic<int> global_value;
int load_global_value() { return global_value.load(std::memory_order_seq_cst); }

然我使用了具有顺序一致性的原子操作(认值),但生成的@L_673_0@中没有什么特别的. GCC和Clang生成的汇编@L_673_0@如下所示:

load_global_value():
    movl global_value(%rip),%eax
    retq

我说几乎相同,因为还有其他原因可能会影响性能.例如:

尽管没有栅栏,但原子操作仍然阻止了一些编译器的优化,例如重新排序说明和消除商店和装载
>如果至少有一个线程写入到同一个高速缓存行上的另一个内存位置,它将性能产生巨大的影响(称为虚假共享)

如此,推荐的实现懒惰初始化的方式是使用std :: call_once.这将为您提供所有编译器,环境和目标体系结构的最佳结果.

std::once_flag _init;
std::unique_ptr<gadget> _gadget;

auto get_gadget() -> gadget&
{
    std::call_once(_init,[this] { _gadget.reset(new gadget{...}); });
    return *_gadget;
}

大佬总结

以上是大佬教程为你收集整理的以轻松的顺序读共享变量:理论上有可能吗?有可能在C吗?全部内容,希望文章能够帮你解决以轻松的顺序读共享变量:理论上有可能吗?有可能在C吗?所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。