我正在尝试实现一个基于数组的无锁二进制搜索树。为了使它同时工作,我应该在方法中锁定一系列数组。我怎样才能实现它?
public int getIndex(int data){
int index = 1;
while(index<this.capacity && this.array[index] != 0){
if(data < this.array[index])
index = index *2;
else if (data> this.array[index])
index = index * 2 + 1;
else
break;
}
if(index >= this.capacity)
return -1;
else
return index;
}
public void insert(int data){
int index = this.getIndex(data);
if (index == -1) {
this.reallocate();
index = this.getIndex(data);
this.array[index] = data;
}
else {
if (this.array[index] == 0)
this.array[index] = data;
}
}
我正在将数据放在getIndex方法中并插入它。所以,在getIndex中,我应该锁定我正在迭代的数组部分。
答案 0 :(得分:0)
如果你的树在插入后没有平衡,它可以长到很大的尺寸(按顺序插入1到100的整数,需要一个大小为2 ^ 100的数组;你没有那么多内存)。所以我假设你的树做了一些重新平衡,以控制内存大小。
要查找密钥,您需要遍历根并最多遍历日志(数组大小)其他节点。如果涉及重新平衡,则可以重新洗牌此路径中的所有节点(直到根)。由于root可以更改,不能同时发生两次写入(其中写入是插入或删除)。此外,重新平衡涉及移动阵列周围;更换根需要移动整个树的一半,这是非常昂贵的。我强烈怀疑,担心性能足以考虑部分锁定支持数组的部分,您希望被拖到树上昂贵的O(n)操作。
读取可以更多并发:它们只会在树上下载一次,并且不会向上重新平衡任何内容(如果您不介意内存耗尽,非重新平衡树也会展示这一点)用于写入,不包括删除)。可以有任意数量的并发读取操作同时工作。而且你可以添加东西而不必担心读取错误 - 所有读取都会找到他们正在寻找的东西,或者偶尔会返回&#34;找不到&#34;如果他们稍微迟到而另一个线程正在写入它们。虽然使用volatile数组,或者其他线程可能永远不会看到更改。
还有一个关于非重新平衡树和delete()的特殊情况。删除(可能)会影响直接向下路径之外的节点(请参阅pictures here)。移动(子)树是昂贵的(线性)与阵列;您打算移动的位需要被锁定,因为在移动期间可能会进行无效读取。不过,我强烈怀疑你不会因为效率低下而实施Delete()。