我使用this post实现other post和此Konrad Rudolph's proposed algorithm中描述的非确定性有限自动机。
我没有使用C ++多图,而是使用HashSet<Character> [][] transitions
数组(这是家庭作业,不能使用Google的番石榴库)。第一维是原始状态,第二维是命运状态,而HashSet定义原点和命运状态之间转换的符号。我的Automaton类的构造函数是:
Automaton (int numberOfStates)
{
this.numberOfStates = numberOfStates;
alphabet = new HashSet<>();
finalStates = new HashSet<>();
transitions = new HashSet[numberOfStates][numberOfStates];
for (int i = 0; i < numberOfStates; i++)
{
for (int j = 0; j < numberOfStates; j++)
{
transitions[i][j] = new HashSet<Character>();
}
}
}
这是我使用此转换数组实现的Konrad Rudolph算法:
public String readStringInAutomaton (char[] inputString,
int initialState)
{
HashSet<Integer> currentStates = new HashSet<>();
HashSet<Integer> nextStates = new HashSet<>();
currentStates.add(initialState);
// for each char in inputString
for (int charIndex = 0; charIndex < inputString.length; charIndex++)
{
char currentTransitionChar = inputString[charIndex];
// for each state in currentStates
for (Integer originState : currentStates)
{
// for each transition starting from originState, current
// char
for (int destinyStateIndex = 0; destinyStateIndex < numberOfStates; destinyStateIndex++)
{
if (transitions[originState][destinyStateIndex]
.contains(currentTransitionChar))
{
nextStates.add(destinyStateIndex);
}
}
}
currentStates = nextStates;
}
}
我已尝试按照Oracle's HashSet documentation中的建议,用Collections.synchronizedSet(new HashSet<>());
替换HashSet的每个实例化。
但是在初始化转换时我得到了一个java.lang.ArrayStoreException:java.util.Collections $ SynchronizedSet。
for (int i = 0; i < numberOfStates; i++)
{
for (int j = 0; j < numberOfStates; j++)
{
transitions[i][j] = Collections
.synchronizedSet(new HashSet<>());
}
}
如何避免这些并发异常?
答案 0 :(得分:5)
您的问题不是关于多线程,而是关于迭代Set
继续添加元素。
您拥有currentStates = nextStates
,然后在您的for循环for (Integer originState: currentStates)
中nextStates.add(destinyStateIndex)
{nextStates
和currentStates
正在执行相同的实例!) - 分配nextStates
。
您应该更正算法:nextStates
必须根据您使用它的方式在循环中的某处重新分配。