Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在一个线程中存储内存;迅速地;在其他线程中可见?_C++_Multithreading_C++11_Atomic_Stdatomic - Fatal编程技术网

C++ 如何在一个线程中存储内存;迅速地;在其他线程中可见?

C++ 如何在一个线程中存储内存;迅速地;在其他线程中可见?,c++,multithreading,c++11,atomic,stdatomic,C++,Multithreading,C++11,Atomic,Stdatomic,假设我想将设备寄存器的内容复制到一个变量中,该变量将由多个线程读取。有没有一个好的通用方法?以下是两种可能的方法的示例: #include <atomic> volatile int * const Device_reg_ptr = reinterpret_cast<int *>(0x666); // This variable is read by multiple threads. std::atomic<int> device_reg_copy;

假设我想将设备寄存器的内容复制到一个变量中,该变量将由多个线程读取。有没有一个好的通用方法?以下是两种可能的方法的示例:

#include <atomic>

volatile int * const Device_reg_ptr = reinterpret_cast<int *>(0x666);

// This variable is read by multiple threads.
std::atomic<int> device_reg_copy;

// ...

// Method 1
const_cast<volatile std::atomic<int> &>(device_reg_copy)
  .store(*Device_reg_ptr, std::memory_order_relaxed);

// Method 2
device_reg_copy.store(*Device_reg_ptr, std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_release);
#包括
volatile int*const Device_reg_ptr=reinterpret_cast(0x666);
//此变量由多个线程读取。
std::原子设备\u注册表\u副本;
// ...
//方法1
const_cast(设备注册副本)
.store(*设备注册ptr,标准::内存顺序\u松弛);
//方法2
device_reg_copy.store(*device_reg_ptr,std::memory_order_released);
std::原子线程围栏(std::内存命令释放);
更一般地说,在面对可能的整个程序优化时,如何正确地控制一个线程中的内存写入在其他线程中可见的延迟

编辑:在您的回答中,请考虑以下情况:

  • 代码在嵌入式系统的CPU上运行
  • 单个应用程序在CPU上运行
  • 应用程序的线程数远远少于CPU的处理器核数
  • 每个核心都有大量的寄存器
  • 该应用程序足够小,在构建其可执行文件时可以成功地使用整个程序优化

如何确保一个线程中的存储不会无限期地对其他线程不可见?

如果要以原子方式更新
device\u reg\u copy
的值,则
device\u reg\u copy.store(*device\u reg\u ptr,std::memory\u order\u released)足够了

不需要将
volatile
应用于原子变量,这是不必要的

std::memory\u order\u released
存储应该产生最少的同步开销。在x86上,它只是一条普通的
mov
指令

但是,如果您希望以这样的方式更新它,使任何先前存储的效果与新值
device\u reg\u copy
一起对其他线程可见,则使用
std::memory\u order\u release
store,即
device\u reg\u copy.store(*device\u reg\u ptr,std::memory\u order\u release)。在这种情况下,读卡器需要按照
std::memory\u order\u acquire
加载
device\u reg\u copy
。同样,在x86
std::memory\u order\u release
上,存储是一个普通的
mov

然而,如果您使用最昂贵的
std::memory_order_seq_cst
存储,它会为您在x86上插入内存屏障

这就是为什么他们说x86内存模型对于C++11来说有点太强了:普通的
mov
指令是
std::memory\u order\u release
存储和
std::memory\u order\u acquire
。x86上没有宽松的存储或加载


我无法推荐足够的文章。

如果您想以原子方式更新
设备注册副本
的值,那么
设备注册副本.store(*device注册副本,std::memory\u order\u released)足够了

不需要将
volatile
应用于原子变量,这是不必要的

std::memory\u order\u released
存储应该产生最少的同步开销。在x86上,它只是一条普通的
mov
指令

但是,如果您希望以这样的方式更新它,使任何先前存储的效果与新值
device\u reg\u copy
一起对其他线程可见,则使用
std::memory\u order\u release
store,即
device\u reg\u copy.store(*device\u reg\u ptr,std::memory\u order\u release)。在这种情况下,读卡器需要按照
std::memory\u order\u acquire
加载
device\u reg\u copy
。同样,在x86
std::memory\u order\u release
上,存储是一个普通的
mov

然而,如果您使用最昂贵的
std::memory_order_seq_cst
存储,它会为您在x86上插入内存屏障

这就是为什么他们说x86内存模型对于C++11来说有点太强了:普通的
mov
指令是
std::memory\u order\u release
存储和
std::memory\u order\u acquire
。x86上没有宽松的存储或加载


<>我不能推荐足够的文章。

< P>对其他线程可见原子存储库的C++标准很模糊。

29.3.12 实现应该使原子存储在合理的时间内对原子负载可见

这是非常详细的,没有“合理”的定义,也不需要立即定义

没有必要使用独立的围栏强制执行特定的内存排序,因为您可以在原子操作上指定这些顺序,但问题是, 关于使用内存围栏,您的期望是什么?
Fences设计用于强制内存操作(线程之间)的排序,但它们不能保证及时的可见性。 您可以使用最强的内存顺序(即
seq_cst
)将值存储到原子变量中,但即使另一个线程在比
store()
更晚的时间执行
load()
, 您可能仍然从缓存中获得一个旧值,但(令人惊讶的是)它并没有违反“发生在之前”关系。 使用更坚固的栅栏可能会有所不同。时间和可视性,但没有保证

<>如果即时可见性很重要,我会考虑使用读修改写(RMW)操作来加载该值。 这些是以原子方式读取和修改(即在单个调用中)的原子操作,并具有保证在最新值上操作的附加属性。 但由于它们必须到达比本地缓存更远的地方,因此这些调用的执行成本也往往更高

正如Maxim Egorushkin所指出的,您是否可以使用比默认值更弱的内存顺序(// thread 1 device_reg_copy.store(*Device_reg_ptr, std::memory_order_release); // thread 2 device_reg_copy.fetch_add(0, std::memory_order_acquire);