Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Concurrency 我应该如何处理共享树数据结构中的线程同步?_Concurrency - Fatal编程技术网

Concurrency 我应该如何处理共享树数据结构中的线程同步?

Concurrency 我应该如何处理共享树数据结构中的线程同步?,concurrency,Concurrency,这只是一种并发刷新 假设我在内存中有一个B+树数据结构-每个节点有多个项,只有叶节点包含项,叶节点还形成一个链表,便于顺序访问。插入和删除通常只影响叶节点,但会导致节点在可能传播到根的进程中拆分或合并 我有一个单线程实现,更新遵循一种预先规划的方法。递归从叶级逐步向上移动,直到节点需要更改为止,从而构建一个链表(在不同的递归中链接局部变量)来描述所需的更改。当它知道需要什么时,它可以检查是否可以分配所有需要的节点,并在退出递归之前通过引用此计划应用所有需要的更改(或不应用) 此实现还“维护”更新

这只是一种并发刷新

假设我在内存中有一个B+树数据结构-每个节点有多个项,只有叶节点包含项,叶节点还形成一个链表,便于顺序访问。插入和删除通常只影响叶节点,但会导致节点在可能传播到根的进程中拆分或合并

我有一个单线程实现,更新遵循一种预先规划的方法。递归从叶级逐步向上移动,直到节点需要更改为止,从而构建一个链表(在不同的递归中链接局部变量)来描述所需的更改。当它知道需要什么时,它可以检查是否可以分配所有需要的节点,并在退出递归之前通过引用此计划应用所有需要的更改(或不应用)

此实现还“维护”更新时的迭代器,因此迭代器不会因插入/删除而无效,除非它们指向的特定项被删除。同一节点内的插入/删除会导致指向该节点的迭代器更新

问题是,我需要使它成为多线程的——同时支持潜在的多个读写器

我希望多个读者能够同时读写,只要不存在腐败的风险。因此,对于阅读,我根本不希望相互排斥的访问,即使是对单个节点的访问。对于编写,我想锁定更改所需的最小节点数。当然,我想避免僵局

谢天谢地,这并不是我真正需要做的事情——但由于我忽视了并发能力,这似乎是一个很好的思维实验

这显然类似于数据库和文件系统必须处理的问题,所以我猜我可能会得到一些关于这类问题的参考,这将是非常好的


那么-我将如何处理这个线程同步?我可以模糊地看到节点上互斥体和/或信号量的角色,但我会使用什么策略来处理它们呢?

这绝对是一项具有挑战性的任务!我看到你是C++程序员,但是我相信C++中有类似java的概念,我会尝试从java的观点来帮助。 因此,对于阅读,我根本不想要互斥访问,即使是对单个节点的访问

您可以使用ReadWriteLock。它可以由多个读线程同时持有,只要没有写入程序。写锁是独占的。你只需要在写东西时使用独占访问权限。你有C++中的类似物吗? 当然,我想避免僵局

只需按级别顺序锁定多个节点(如从上到下)。这将保证您免于死锁(这将是smth类似于兰波特的烘焙算法)

至于数据库,它们通过杀死一个进程来解决死锁:-)

另一种策略是以类似Cliff Click实现解锁哈希映射(覆盖所有情况的状态机)的方式实现解锁树结构:


干杯

锁定顺序是更新中读写节点的混合。从纯写的意义上讲,自上而下的锁定没有死锁的意义——但在插入或删除到某个位置(不仅仅是键)时,首先要确定哪些节点受到影响,从叶中的项向上移动(可能因此读取自下而上的锁定)。当然,插入一个键,首先要进行自顶向下的搜索。请注意,也许自下而上的锁定可以工作——如果一致的话。对于Read WrreBoCK-C++没有标准的同步原语,尽管很多人每天使用非标准的同步原语。但我想了解的更多的是ReadWriteLock是如何实现的。我刚刚看了一下,两个基本锁的事情是有意义的。在一致的锁定方向上,我想知道(当你自然需要以错误的顺序获得一些锁时)释放锁,以正确的顺序重新锁定,然后检查、修复,或者,如果这些节点在解锁时发生了重大变化,则从头开始重新执行更新计划。从软件事务内存中窃取想法。仅仅因为某些事情可能会出错并不一定意味着你要克服困难来阻止它。如果概率足够低,只要你能在它发生时检测并修复/重做,那就没什么大不了的。虽然我不能回答上述所有问题,但我可以说拥有可伸缩的并发树结构是已知的问题。我已经研究了java中的内容——还有ConcurrentSkipListMap(基本上是使用跳过列表实现的TreeMap)。也许这和你需要的差不多?无论如何,这个类是由DougLea编写的,有很多od文档,值得一看。