Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.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
Multithreading 是否有任何有效的(子)树锁定机制?_Multithreading_Algorithm_Data Structures_Tree_Locking - Fatal编程技术网

Multithreading 是否有任何有效的(子)树锁定机制?

Multithreading 是否有任何有效的(子)树锁定机制?,multithreading,algorithm,data-structures,tree,locking,Multithreading,Algorithm,Data Structures,Tree,Locking,我有一个树T,其中的节点可以通过它们的路径进行寻址(节点的有效负载包含一些names,它们可以粘在一起形成一个路径)。我想要的是某种机制(算法、辅助数据结构等),允许在给定路径P0的情况下,以如下方式锁定整个子树: 尝试锁定任何路径P1(其中P1以P0开始,即P1属于锁定的子树)将导致P1的锁定是P0的锁定(当然,它可能不是完全相同的锁定,但是对P1的操作应该等到P0的锁定是免费的) 但是当P0锁被释放时,P2的任何锁,其中P2以P0开始,而不是P2以P1开始,即P2子树和P1子树是不同的,将

我有一个树
T
,其中的节点可以通过它们的路径进行寻址(节点的有效负载包含一些
name
s,它们可以粘在一起形成一个路径)。我想要的是某种机制(算法、辅助数据结构等),允许在给定路径
P0
的情况下,以如下方式锁定整个子树:

  • 尝试锁定任何路径
    P1
    (其中
    P1以P0
    开始,即
    P1
    属于锁定的子树)将导致
    P1
    的锁定是
    P0
    的锁定(当然,它可能不是完全相同的锁定,但是对
    P1
    的操作应该等到
    P0
    的锁定是免费的)
  • 但是当
    P0
    锁被释放时,
    P2
    的任何锁,其中
    P2以P0
    开始,而不是
    P2以P1
    开始,即
    P2
    子树和
    P1
    子树是不同的,将为这两条路径授予不同的锁,依此类推
我处理过几次这个任务,但最终我得到了一个过于复杂的代码,代码凌乱,并且使用了某种树来存储锁本身,这比我试图锁定的树还要重


如果我的问题不清楚,请告诉我您是否想看一些图纸/图表或任何有帮助的东西。

免责声明:这与我在2009年做的硬件作业非常相似,所以我记得基本的想法,而不是细节。无论如何,我建议如下:

树中的每个节点都有自己的锁。每个锁定操作都从树的根开始,然后向下指向所需的节点,在向下的过程中锁定每个节点。如果遇到锁定的节点(不是根节点),锁定操作将终止(未成功),或设置为等待并重试(如忙等待)。如果根目录本身被锁定,它可能是另一个正在进行的操作的临时锁定。如果根节点未锁定,但内部节点已锁定,则它实际上已锁定。
解锁可能会有所不同,但不确定是否需要从根目录向下执行路径。(可能是这样,所以这是值得检查的)

编辑:

在锁定所需节点后,在树上运行时,还要将树路径上的节点标记为子树中某些节点已锁定的节点。这样,当您锁定一个节点时,您可以知道该子树中是否有已锁定的节点。

我可能遗漏了一些内容,但我认为您的需求可以通过首先计算树的逆传递闭包来轻松解决,该闭包可以在线性时间内计算

其基本思想是,知道一个节点是否可以安全操作,可以简化为知道它的任何父节点是否没有被锁定

为此,需要保留一组锁定的节点。锁定子树只需将其根添加到锁定的_节点集中即可,解锁子树则通过从同一集中移除其根即可(booth O(1)操作) 给定一个节点,要知道是否可以对该节点(或相当于该节点上的子树)进行操作:

Intersection(parents(node),locked_nodes) = empty_set

集合“parent(node)”是从逆传递闭包中提取出来的。

只是想澄清一下:假设
A
是根,有两个子
B
C
。当
A
被锁定时,
B
C
不能被锁定(它们位于
A
的子树中),但是如果
A
未被锁定,
B
C
可以单独锁定。这是正确的吗?@shapiro.yaacov,是的,这是正确的。第一个条件很容易实现,这是让我头疼的第二个部分。你可能想看看数据库是如何锁定它们的b树的。不知道这实际上是如何工作的,但我认为他们必须以某种方式有效地解决这个问题。当您检查所需节点下的任何内容是否被锁定时,所描述的方案无法处理该部分。实际上,在执行锁定操作时(您始终只能同时锁定单个子节点),执行单个全局锁定的效率似乎相当低,这样您就可以通过只等待一个条件变量来避免每个节点一个锁定的高昂成本(适用于等待子节点的所有人)和原子整数。这样,您也可以避免始终锁定根节点。@Voo-您仍然需要锁定从根节点到所需节点的路径,以便更新该路径上节点的值,否则您将陷入混乱(当两个线程想要锁定一个节点及其子节点时会发生什么?)原子比较交换。@Voo-请详细说明。比较交换(弱或强)对于一个节点来说是很好的。而不是对于节点的路径。如果一个节点想要被锁定,但是它的子树中的一个节点已经被锁定,你该如何处理这种情况?如果你检查从每个节点到根的路径(看看所需的节点是否在该路径上),可能需要
O(n logn)
。您可以计算传递闭包,并检查给定节点的传递闭包中是否有任何节点已被锁定。这将为您提供一个固定时间的检入。但是从我从您的描述中了解到的情况来看,我不明白为什么在锁定节点之前需要检查锁定的子树。您能澄清一下吗?Imho,使用锁定是确保没有人接触该子树中的任何节点。这意味着如果子树的某个部分已锁定,则无法锁定该子树。这意味着您可以更改该子树中的所有节点,而该子树中已锁定的部分实际上不可访问you@shapiro.yaacov好的,我明白了,如果是这样的话,你需要一个中转站和逆传递闭包,正如我在前面的评论中所说的