【发布时间】:2010-05-29 17:53:29
【问题描述】:
对于我正在研究的算法,我尝试开发一种黑名单机制,可以以特定方式将数组列入黑名单:如果“1、2、3”被列入黑名单,“1、2、3、4、5”也被列入黑名单被列入黑名单。
到目前为止,我对我提出的解决方案感到非常满意。但是当我从多个线程访问黑名单时,似乎出现了一些严重的问题。方法“包含”(参见下面的代码)有时会返回 true,即使数组未列入黑名单。如果我只使用一个线程,则不会出现此问题,因此很可能是并发问题。
我试过添加一些同步,但它没有改变任何东西。我还使用 java.util.concurrent 类尝试了一些稍微不同的实现。有关如何解决此问题的任何想法?
public class Blacklist {
private static final int ARRAY_GROWTH = 10;
private final Node root = new Node();
private static class Node{
private volatile Node[] childNodes = new Node[ARRAY_GROWTH];
private volatile boolean blacklisted = false;
public void blacklist(){
this.blacklisted = true;
this.childNodes = null;
}
}
public void add(final int[] array){
synchronized (root) {
Node currentNode = this.root;
for(final int edge : array){
if(currentNode.blacklisted)
return;
else if(currentNode.childNodes.length <= edge) {
currentNode.childNodes = Arrays.copyOf(currentNode.childNodes, edge + ARRAY_GROWTH);
}
if(currentNode.childNodes[edge] == null) {
currentNode.childNodes[edge] = new Node();
}
currentNode = currentNode.childNodes[edge];
}
currentNode.blacklist();
}
}
public boolean contains(final int[] array){
synchronized (root) {
Node currentNode = this.root;
for(final int edge : array){
if(currentNode.blacklisted)
return true;
else if(currentNode.childNodes.length <= edge || currentNode.childNodes[edge] == null)
return false;
currentNode = currentNode.childNodes[edge];
}
return currentNode.blacklisted;
}
}
}
【问题讨论】:
-
我觉得没问题。同步应该防止所有问题同时调用 add 和 contains,所以我猜你的问题出在调用它们的代码上。顺便说一句,通过同步,您无需在节点 volatile 中声明变量。
-
对我来说看起来也不错 :) 变量只是易变的,因为我认为它可能会有所帮助。但它们是否不稳定似乎没有什么区别。
-
为什么黑名单方法是公开的?你确定没有其他线程调用它吗?
-
@Istao,黑名单方法在私有内部类节点中,除非他们得到根节点的引用(他们没有),否则没有人可以调用它。
-
@Istao,它在一个私有内部类中,所以没有人可以从外部调用它——至少如果上面是
Blacklist的完整定义。 @Johannes,是这样吗?
标签: java arrays concurrency