My tests show that the following code is not thread safe, although the class has no state and all the state shared between methods is passed as parameters from method to method. One instance of the following class is invoked by multiple threads.
public class ThingFinder {
Token findFoo(TokenIterator<? extends Token> iterator,
Token start, final Token limit) {
Token partOfFoo = searchForward(iterator, start, new TokenSearcher() {
int maxTokens = 5;
@Override
public SearchAction assessToken(Token aToken) {
if (limit != null && (aToken.getStart() >= limit.getStart())) {
return SearchAction.STOP;
}
if (maxTokens-- == 0) {
return SearchAction.STOP;
}
if (isAThing(aToken)) {
return SearchAction.MATCH;
} else {
return SearchAction.IGNORE;
}
}
});
return partOfFoo;
}
public Token extractAThing(TokenIterator<? extends Token> iterator) {
Token start = findStart(iterator);
Token limit = findLimit(iterator, start);
return findFoo(iterator, start, limit);
}
}
The goal was to make this class thread safe because it is stateless, and all the state that needs to be shared between methods is passed from method to method as parameters. However, tests show that sometimes we get an exception with a null pointer on this line:
if (limit != null && (aToken.getStart() >= limit.getStart())) {
It seems that once between checking a null value and calling getStart, the parameter constraint becomes zero.
, findFoo :
Token findFoo(TokenIterator<? extends Token> iterator, Token start,
final Token limit) {
, ? , , , Unsafe?