Для алгоритма, над которым я работаю, я попытался разработать механизм черного списка, который может черным списком массивов определенным образом: если «1, 2, 3» занесено в черный список «1, 2, 3» , 4, 5 "также считается внесенным в черный список.
Я доволен решением, которое я придумал до сих пор. Но, похоже, есть некоторые серьезные проблемы, когда я получаю доступ к черному списку из нескольких потоков. Метод «содержит» (см. Код ниже) иногда возвращает true, даже если массив не внесен в черный список. Эта проблема не возникает, если я использую только один поток, поэтому, скорее всего, это проблема параллелизма.
Я попытался добавить некоторую синхронизацию, но ничего не изменил. Я также пробовал несколько несколько разных реализаций с использованием классов java.util.concurrent. Есть какие нибудь идеи как это починить?
Проблема параллелизма с массивами (Java)
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;
}
}
}
Это выглядит нормально для меня. Синхронизация должна предотвращать одновременное вызов и добавление всех проблем, поэтому я предполагаю, что ваша проблема связана с кодом, вызывающим их. BTW, с синхронизацией вам не нужно объявлять переменные в узле неустойчивыми. – starblue
Мне тоже все хорошо :) Переменные просто волатильны, потому что я думал, что это может помочь. Но, похоже, они не изменчивы, если они нестабильны или нет. – Johannes
Почему метод blacklist является общедоступным? Вы уверены, что ни один другой поток не назвал это? – Istao