c++ - 多线程深度复制

标签 c++ multithreading constructor

在作为多线程 C++ 代码一部分的对象的构造函数中执行深度复制的最佳方法是什么?

最佳答案

取决于您的数据结构。

我猜你面临的问题(虽然你没有这么说)是潜在的锁定反转。如果您进行深度复制,那么您可能会为需要复制的各种对象获取一把或多把锁。

如果您可以定义一个 DAG(即偏序),其中节点是系统中的每个锁,并且您可能想要使用的每个锁组合都由边连接,那么您可以确保锁是从来没有在不同的线程中接受过不同的命令。因此,特别是您不会获得锁定反转。一个典型的规则是最后获取“最一般”的锁,因为这往往会最小化争用。

但是,如果您正在深度复制一大堆“WidgetBox”中的一个,每个“WidgetBox”都包含基本上无法区分的“Widget”,并且框的内容之间可能存在重叠,那么您自然会在定义锁定顺序时遇到问题。此外,您必须首先锁定 WidgetBox(即使它是“最通用”的对象),因为没有该锁定,您无法判断还需要锁定什么。如果 Widget 具有可比性,您可以按顺序锁定每个 Widget,复制并释放所有内容。讨厌。

另一种方法是定义一个在所有 Widget 和 WidgetBox 之间共享的锁。这可能会引入很多争用,在这种情况下,乐观锁定可能会有所改善,前提是不要与拷贝同时发生太多修改。

另一种选择可能是放宽您对拷贝所做的保证 - 您可以首先锁定 WidgetBox,浅复制它(使用引用计数或其他任何方式),而不是要求从深层结构的可识别状态制作完整拷贝- refcount 上的锁通常是“最终内部锁”,因此没有反转风险),释放 WidgetBox 锁,然后依次复制每个 Widget。如果 Widget 具有内部结构,请使用相同的方法复制它们。结果可能包含处于某个状态的 Widget,直到它在另一个线程中从 WidgetBox 中删除后才达到该状态,或其他类似的不协调,因此如果这是 Not Acceptable ,那么您不能使用此方法。但是,如果您在每个线程中一次只锁定一个对象,那么您将无法获得锁定反转。

最后一个可能的“核”选项是使所有内容不可变,并始终在修改时复制。如果什么都不能修改,那么您就不需要任何锁(尽管在线程之间传递引用时您仍然需要内存屏障)。

如果这些都不起作用,那么除非我忘记了什么,否则你就超出了我的经验。我推测数据库实现是许多与锁相关的聪明之处,这将是寻求创意的领域。

关于c++ - 多线程深度复制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/176691/

相关文章:

c++ - CUDA:cudaMallocManaged 是否处理退出?

c# - 在多个线程中使用单个位图 Graphics.CopyFromScreen 的最有效方法?

java - 当其中一个线程完成时停止所有线程

c# - 如何使属性设置一次且不能更改?

c++ - 反转模板(整数)参数的顺序

c++ - 在一个范围内推送五个对象指针,然后检查对象的 bool 是否为 false,会出错

c++ - 按值传递的结构,在 C -> C++ 回调函数 (gcc 4.1) 期间损坏

multithreading - 多个线程调用同一函数的问题

javascript - 你能创建一个 JSON 构造函数吗?

c# - 为什么不能创建抽象类实例但可以调用其构造函数?