多线程环境中C++内存访问
Memory access in C++ multithreading environment
我有一个问题,即主线程中的函数被阻塞,直到在另一个线程中设置局部变量。我使用信号量来阻止主线程执行:
int sendRequest(Message request, void *data)
{
semaphore waitForReply;
volatile int result = 0;
volatile int retData[100];
client->sendRequest(request, [&result, &retData](const Message& reply){ // Callback is called from a different thread
result = reply.result;
memcpy(retData, reply.retData, sizeof(retData));
waitForReply.signal();
})
waitForReply.wait();
//At this line we want result var to be updated.
memcpy(data, retData, sizeof(retData));
return result;
}
问题是使用 volatile int 结果是否保证返回的结果是从回调接收的实际值? 这是解决此问题的最佳方法还是使用普通变量和互斥锁更好?
数组 retData 的情况如何?(请不要介意数组的大小(
Volatile
在C 或 C++ 中对多线程代码没有用,因为它不会创建内存屏障。但是,您的代码中没有任何内容需要内存屏障,因此您已经很好了。
错误代码的一个示例是:
// initially
my_pointer = nullptr;
ready_flag = false;
// thread 1
my_pointer = some_pointer_here;
ready_flag = true;
// thread 2
while (!ready_flag) /* wait */;
my_pointer->foo = bar;
这段代码很危险,因为很多事情可以使写入ready_flag
在写入my_pointer
之前变得可见,即使它在源代码中排在第二位。在这种情况下,您可以在为my_pointer
分配值之前访问它。
内存屏障是一种指令,用于强制执行内存写入何时可见的特定顺序。例如,该代码需要在写入my_pointer
和写入ready_flag
之间建立内存屏障。C++标准库为此提供了std::atomic_thread_fence
。此外,std::atomic
类型都可能生成内存障碍。
在您的情况下,您的变量没有相互依赖关系(除了整个操作必须已完成(,并且信号量的wait
方法几乎肯定存在障碍。
在内核/CPU 之间实现缓存和内存一致性的确切方法取决于平台。AFAIK,在x86和ARM衍生产品上,你根本不需要做任何事情。在更疯狂的平台上,这通常由内存围栏处理,无论如何您都会使用它。
生成的缓冲区中的数据很好。在 lambda 中调用 memcpy 可确保在信号量 waitForSignal 发出信号之前完整复制数据。 但。。。
- 不,在这种情况下,volatile 关键字不执行任何操作。 MEMCPY 不受易失性关键字的影响。
volatile
仅影响代码的优化方式。 - 为什么不捕获
data
并让 lambda 直接填充该缓冲区? 这将保存副本。 - 我没有看到任何参数来说明输出缓冲区的大小
data
. 这不是很好的做法。 我建议你考虑使用 std::vector 或其他一些安全的方式来实现缓冲区。
相关文章:
- C++尝试深度复制唯一指针时出现内存访问冲突
- 如何使用 MPI 的远程内存访问 (RMA) 功能并行化数据聚合?
- CRTP - 危险的内存访问?
- C++ Python 的扩展 - 安全内存访问和内存布局
- 在Visual Studio中查找非法内存访问
- C++内存访问违反内存大块
- 数组中未映射的内存访问从python传递到c++
- 使用加速进程间创建消息队列 - 内存访问冲突
- C 指针转换会导致内存访问冲突
- 为什么代码会抛出非法内存访问错误
- 多线程环境中C++内存访问
- CUDA 中的递归返回非法内存访问
- 为什么创建进程 API 调用会导致内存访问冲突?
- 在 C++ 中遍历链表比在具有类似内存访问的 Go 中慢
- 确定打开进程的内存访问位置
- 存在内存访问异常,但我不确定我的代码中出了什么问题
- 指向结构的指针的 2D 数组.内存访问问题
- GPU 内存访问和使用 (CUDA)
- 在实时程序中是动态内存访问有害的
- 随机 mmaped 内存访问比堆数据访问慢 16%