0

我用 C++ 编写了一个程序(假设 X),它创建了一个数据结构,然后连续使用它。现在我想修改那个数据结构而不中止之前的程序。我尝试了两种方法来完成这项任务:

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

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

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

4

2 回答 2

0

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

翻译成代码,前者意味着拥有一个锁或互斥锁来控制对数据结构的访问,以便在任何时候只有一个线程可以修改它。

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

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

于 2012-05-16T22:27:53.247 回答
0

第一点:这不是一个小问题。要完全处理好它,您需要设计一个系统,而不仅仅是一两个快速破解。

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

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

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

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

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

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

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

于 2012-05-16T20:27:15.000 回答