多线程深度拷贝
Multi-Threaded Deep Copies
在作为多线程C++代码一部分的对象的构造函数中执行深层复制的最佳方法是什么?
取决于数据结构。
我猜你面临的问题(虽然你没有这么说)是潜在的锁定反转。如果要进行深度复制,那么可能会为需要复制的各种对象使用一个或多个锁。
如果可以定义一个 DAG(即偏序),其中节点是系统中的每个锁,并且您可能想要采用的每个锁组合都通过边缘连接,则可以确保锁永远不会在不同的线程中以不同的顺序获取。因此,特别是您不会获得锁定反转。一个典型的规则是将"最一般"的锁放在最后,因为这往往会最大限度地减少争用。
但是,如果您正在深度复制一大堆"WidgetBox"中的一个,每个"Widget"都包含基本上无法区分的"Widget",并且框的内容之间可能存在重叠,那么您自然就无法定义锁定顺序。此外,您必须先锁定WidgetBox(即使它是"最通用"的对象),因为如果没有该锁定,您将无法判断还需要锁定的内容。如果 Widget 具有可比性,您也许可以按顺序锁定每个控件,执行复制并释放所有内容。讨厌。
另一种方法是定义在所有 Widgets 和 WidgetBox 之间共享的单个锁。这可能会引入很多争用,在这种情况下,乐观锁定可能会改善事情,前提是不会与副本同时发生太多修改。
另一种选择可能是放宽您对副本的保证 - 而不是要求从深层结构的可识别状态制作完整副本,您可以首先锁定 WidgetBox,浅拷贝它(使用 refcount 或其他任何东西 - refcount 上的锁通常是"终极内锁",因此不是反转风险), 释放小部件框锁,然后依次复制每个小部件。如果小部件具有内部结构,请使用相同的方法来复制它们。结果可能包含一个 Widget 处于直到它从另一个线程中的 WidgetBox 中删除后才达到的状态,或者其他此类不一致,因此如果这不可接受,那么您不能使用此方法。但是,如果您在每个线程中一次只锁定一个对象,则无法获得锁定反转。
最后一个可能的"核"选项是使所有内容不可变,并始终在修改时复制。如果什么都不能修改,那么你不需要任何锁(尽管在线程之间传递引用时你仍然需要内存屏障)。
如果这些都不起作用,那么除非我忘记了什么,否则你就没有我的经验了。我推测数据库实现是许多与锁相关的聪明才智的地方,这将是寻求想法的领域。
fork()
我只是在开玩笑。 但这太有趣了,不能错过:)
我认为 onebyone 已经涵盖了您的大部分选择。 除了,也许,退后一步,看看你是否能找到一种方法来避免首先做深度复制......
我的第一个冲动(我不是专家):
锁定代码用于写入该对象的该对象。进行深层复制时,请锁定对象,执行深层复制,然后将其解锁。
或者,我在这里错过了什么?
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- OpenGL在启用深度测试时不会丢弃我的碎片
- 如何在没有数据拷贝的情况下从指针创建一个Eigen VectorXd对象
- C++尝试深度复制唯一指针时出现内存访问冲突
- 试图找到二叉树的深度
- 与浅拷贝构造函数和深拷贝构造函数混淆
- 操纵安卓相机的深度图导致应用程序崩溃
- 深度值没有意义 R200 相机
- 对如何制作双链表的深度副本感到困惑?
- 以C++访问 HoloLens 2 深度图像
- 在 c++ 中使用深度复制的运算符重载
- 使用复制构造函数修复浅拷贝
- 指向指向对象的指针数组的指针的深度拷贝
- 如何执行char *的深度拷贝
- Poco::JSON::Object的深度拷贝
- c++深度拷贝中的内存泄漏
- 链表的深度拷贝
- 一个结构体的深度拷贝,它嵌入了许多简单的变量和一个嵌套结构体
- 如何创建一个QList的深度拷贝(Qt 4.8)
- 多线程深度拷贝