Стивен С. Хорошие вещи. Дополнительная информация: Если вы не знаете, как обстоят дела с наборами, вы можете использовать «глобальную» блокировку всякий раз, когда оба набора будут сравниваться:
private static final Object lock = new Object(); // May be context-local.
[...]
synchronized (lock) {
synchronized (s1) {
synchronized (s2) {
return s1.equals(s2);
}
}
}
Если наборы могут быть оспорены, вы можете в большинстве случаев упорядочивать по хэш-коду идентификатора и возвращаться к глобальной блокировке:
int h1 = System.identityHashCode(s1);
int h2 = System.identityHashCode(s2);
return
h1<h2 ? lockFirstEquals(h1, h2) :
h2<h1 ? lockFirstEquals(h2, h1) :
globalLockEquals(h1, h2);
Иногда вы можете использовать альтернативный алгоритм. IIRC, StringBuffer
может зайти в тупик с добавлением (хотя комбинация операций над объектами не имеет большого смысла). Это может быть реализовано как:
public StringBuffer append(StringBuffer other) {
if (other == null) {
return append("null");
}
int thisHash = System.identityHashCode(this);
int otherHash = System.identityHashCode(other);
if (thisHash < otherHash) {
synchronized (this) {
synchronized (other) {
appendImpl(other);
}
}
} else if (otherHash < thisHash) {
synchronized (other) {
synchronized (this) {
appendImpl(other);
}
}
} else {
append(other.toString()); // Or append((Object)other);
}
return this;
}
Лучшим решением, вероятно, было бы изменить стратегию потоков, чтобы вам здесь не нужна была блокировка.