如何在进程已经在访问数据结构时修改数据结构



我用c ++编写了一个程序(假设X(,它创建了一个数据结构,然后连续使用它。现在我想在不中止上一个程序的情况下修改该数据结构。我尝试了2种方法来完成此任务:

  1. 在同一个程序X中,我首先创建了数据结构,然后尝试创建一个子进程,该子进程开始出于某种目的访问和使用该数据结构。父进程继续执行,并要求用户进行任何修改,如插入、删除等,并从控制台获取输入,随后完成修改。这里的问题是,它不会修改子进程正在使用的数据结构的副本。后来,我发现这无济于事,因为子进程正在使用自己的数据结构副本,因此通过父进程所做的修改不会反映在其中。 但可以肯定的是,我不希望这种情况发生。所以我选择了多线程。

  2. 我没有创建子进程,而是创建了一个访问该数据结构并使用它的线程,并尝试从不同线程中的控制台获取用户输入。甚至由于线程之间的切换非常快,这不起作用。

所以,请帮我解决这个问题。我希望修改反映在原始数据结构中。此外,我不希望该过程(连续访问和使用它(有时等待,因为它对时间至关重要。

第一点:这不是一个微不足道的问题。为了很好地处理它,你需要设计一个系统,而不仅仅是一两个快速的黑客。

首先,为了支持动态更改,您几乎肯定希望在 DLL 或 .so 之类的代码中定义数据结构,以便您可以动态加载它。

如何继续的部分内容将取决于您是在谈论严格存储在内存中的数据,还是更面向文件的数据。在后一种情况下,一些决策将取决于新形式的数据结构是否大于旧形式的数据结构(即,是否可以就地升级(。

让我们从简单开始,假设您只处理内存中的结构。每个数据项将表示为一个对象。除了访问数据所需的任何内容之外,每个对象还将提供锁定,以及从该对象的先前版本的对象构建自己的方法(懒惰 - 即按需,而不仅仅是在ctor中(。

加载定义新对象类型的 DLL/.so 时,将创建一个与当前现有对象集合大小相同的集合。每个新对象都将处于"懒惰"状态,在那里它被初始化,但尚未真正从旧对象创建。

然后,

您将启动一个线程,该线程使程序的其余部分知道新集合,然后遍历新对象的集合,锁定旧对象,使用它创建新对象,然后销毁旧对象并将其从旧集合中删除。当它尝试锁定旧对象时,它将使用相当短的超时(即,如果一个对象正在使用中,它不会等待很长时间,只需继续下一个。它将反复迭代,直到所有旧对象都已更新并且旧对象的集合为空。

对于磁盘上的数据,情况可能大致相同,只是对象集合提供对磁盘上数据的访问。您可以创建两个单独的文件,并将数据从一个文件复制到另一个文件,并根据需要进行转换。

另一种可能性(特别是如果数据可以就地升级(是使用单个文件,但在每条记录中嵌入版本号。读取一些原始数据,检查版本号,并使用适当的代码来读/写它。如果您正在读取旧版本号,请使用旧代码读取,转换为新格式,然后以新格式写入。如果没有要更新的空间,请将新记录写入文件末尾,然后更新索引以指示新位置。

您的并发访问方法类似于在满是蒙着眼睛的幼儿的教室之间共享蛋糕。毫不奇怪,你最终会得到一个粘稠的混乱。每个蹒跚学步的孩子要么必须等待轮到他们挖,要么确切地知道她一个人可以触摸蛋糕的哪一部分。

转换为代码,前者意味着具有控制对数据结构的访问的锁或互斥锁,以便只有一个线程可以随时修改它。

后者可以通过让数据结构由线程就地修改来完成,

每个线程都确切地知道他们可以更新数据结构的哪些部分,例如,通过传递一个结构,其中包含要更新的范围的详细信息,有效地事先拆分数据。这些不应该重叠,迭代器不应该失效(例如通过调整大小(,这对于给定的问题可能是不可能的。

处理资源竞争的算法有很多,所以这被大大简化了。分布式计算是计算机科学中致力于此类问题的重要领域;研究问题(你没有提供细节(,不要指望魔法。

最新更新