【发布时间】:2022-01-17 14:37:27
【问题描述】:
在我的 Qt C++ 应用程序中,我有两个主线程:GUI 线程和渲染线程。 GUI 线程管理可以创建和编辑的DataObject 结构列表,而渲染线程绘制对象(渲染线程无法修改数据对象)。我需要一种在两个线程之间共享数据对象的方法(渲染线程每帧可以渲染数千个对象,并且对象通常存储数百对浮点数)。
目前,我的设计策略包括存储 shared_ptr 的数据对象并将共享指针列表从 GUI 线程传递到渲染线程。当 GUI 线程正在修改数据对象并且渲染线程也试图读取相同的数据对象时,我使用互斥锁和锁来防止数据竞争。
另一方面,查看 Qt 源代码,我发现大量使用了 Copy-on-write 技术,该技术本质上涉及在只读访问时数据对象的浅拷贝和对于写访问的深拷贝。 Qt 还提供了方便的类,例如QSharedData 类来实现您自己的隐式共享对象。
因此,就我而言,我正在考虑使用写时复制,以便我可以使用这种技术实现我的DataObject。我可以直接传递DataObject 实例,而不是将共享指针传递给渲染线程(当然内部数据仍然使用指针存储),如果 GUI 线程试图修改数据对象,它只会复制数据并且这两个线程将继续运行,就好像它们拥有数据对象一样(渲染线程最终会丢弃它的副本)。
现在,在我看来,写时复制在 C++ 世界(Qt 之外)中非常不受欢迎,而且我还没有找到很多其他代码库中使用它的例子。在我的场景中使用写时复制有什么缺点?有什么我应该注意的陷阱吗?
【问题讨论】:
-
您的“阅读”线程应该何时更新其“修改”数据?
-
基本上我的 GUI 线程的每一帧都会发送一个要渲染的数据对象列表。所以渲染线程会在下一帧开始时接收到修改后的数据。
-
我强烈推荐 stlab::copy_on_write
github.com/stlab/libraries/blob/main/stlab/copy_on_write.hpp 与 Qt 不同的是,它明确说明了潜在副本的位置。
标签: c++ multithreading qt copy-on-write