Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.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

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_Thread Safety - Fatal编程技术网

C++ 线程中的内存范围共享:确保数据不会卡在缓存中

C++ 线程中的内存范围共享:确保数据不会卡在缓存中,c++,multithreading,thread-safety,C++,Multithreading,Thread Safety,当将内存位置的地址从一个线程发送到另一个线程时,如何确保数据没有卡在CPU缓存中,并且第二个线程实际读取了正确的值?(我正在使用socketpair()发送 从一个线程到另一个线程的指针) 和相关问题,C++编译器如何与线程原语一起,找出同步处理需要特别处理的内存地址。 struct Test { int fld; } thread_1 ( ) { Test *ptr1 = new Test; ptr1->fld = 100; ::write(write_fd, &

当将内存位置的地址从一个线程发送到另一个线程时,如何确保数据没有卡在CPU缓存中,并且第二个线程实际读取了正确的值?(我正在使用socketpair()发送 从一个线程到另一个线程的指针)

<>和相关问题,C++编译器如何与线程原语一起,找出同步处理需要特别处理的内存地址。
struct Test { int  fld; }

thread_1 ( ) {
  Test *ptr1 = new Test;
  ptr1->fld = 100;
  ::write(write_fd, &ptr1, sizeof(ptr1));
}

thread_2 () {
  Test *ptr2;
  ::read(read_fd, &ptr2, sizeof(ptr2));
  // WHAT MAGIC IS REQUIRED TO ENSURE THIS ?
  assert(ptr2->fld == 100 );
}

如果希望在同一进程中的线程之间传递值,我将确保
std::atomic
作为字段类型,并使用相关的setter和getter函数。显然,将指针从一个进程传递到另一个进程根本不起作用,除非它来自一个保证在两个进程中具有相同地址的内存区域-例如共享内存,但是您不应该需要套接字

编译器通常不知道如何处理缓存,除了
原子类型(从技术上讲,原子通常使用单独的指令处理,而不是缓存刷新和缓存失效,处理器硬件处理相关的“与其他处理器谈论缓存内容”)

当在进程之间或进程内传递时,操作系统(当然会有bug)会做类似的事情。但是对于传递指针,您不能依赖于此,新接收的指针值是正确的,但是指针指向的内容不是缓存管理的

在某些处理器中,可以使用内存屏障来调整线程之间内存内容的正确顺序。这迫使处理器“在此点之前执行所有内存操作”。但是,在系统调用(如
读取
写入
)的情况下,操作系统应为您处理好这一问题,并确保在
读取
开始读取它要存储在套接字缓冲区中的内存之前,内存已正确写入,而
write
在存储数据后会有一个内存障碍(在本例中是指针的值,但内存障碍会影响该点之前的所有读取和/或写入)


如果要实现自己的原语来传递数据,而处理器没有缓存一致性(大多数现代处理器都有),则还需要为写入端添加缓存刷新,为读取端添加缓存失效。这是架构依赖的,在标准C或C++中没有支持(在某些处理器中,只有OS功能[内核模式])可以刷新或使缓存内容无效,在其他处理器中,它可以在用户模式代码中完成——这些操作的粒度也会发生变化,可能需要刷新或失效整个缓存系统,或者在32, 64次或128字节的单个行可以同时刷新)

C++。您不需要关心缓存之类的实现细节。你唯一需要做的就是确保C++在关系之后发生。 正如Mats Peterson的回答所示,

std::atomic
是实现这一目标的一种方法。对原子变量的所有访问都是有序的,尽管顺序可能不是静态确定的(即,如果有两个线程试图写入同一个原子变量,则无法预测最后发生的写入)

另一种强制同步的机制是
std::mutex
。线程可以尝试锁定互斥体,但一次只能有一个线程锁定互斥体。其他线程将阻塞。编译器将确保当一个线程解锁互斥锁,而下一个线程锁定互斥锁时,第一个线程的写操作可以被第二个线程读取。如果这需要刷新缓存,编译器将对此进行安排


另一种机制是
std::atomic\u thread\u fence
。如果线程之间共享多个对象(所有对象都在同一方向上),则此选项非常有用。您可以将其中一个元素设置为原子元素,并在该原子变量上“附加”栅栏,而不是将它们全部设置为原子元素。然后最后写入原子变量,然后首先读取。显然,这最好封装在一个类中。

想知道如何在原子中放置完整的结构<代码>结构测试包装器{std::atomic wrapped;
,ptr1和ptr2是*TestWrapper。原子类型仅适用于简单类型,因此您必须声明每个字段
atomic
。或者执行其他操作……;)嗯。实际上,我还有一个缓冲区,发送到另一个线程以写入网络;我想知道这是否是一个通用设计!谢谢帮助。如果您有中等大小的数据(以千字节为单位)结构,那么很可能最好发送一个副本,而不是指针[显然对于没有序列化机制的类不起作用]。请注意,如果希望非一致性处理器缓存同步,则开销非常大-所花费的主要时间是将受影响的数据实际写入内存,并以缓存线大小的块在受影响的内存区域上进行迭代。因此,进行可能适合缓存的复制通常比缓存维护快。