Мне интересно, гарантируется ли эта идея кэширования для работы:Безопасна ли эта кеширующая нить?
@RequiredArgsConstructor @Getter class CacheEntry {
static CacheEntry get(String string, int start) {
int hash = string.hashCode()^start; // or something better
int index = hash & (cache.length-1);
CacheEntry result = cache[index];
if (result!=null && result.matches(string, start)) return result;
result = new CacheEntry(string, start, computeSomething(string, start));
cache[index] = result;
return result;
}
private boolean matches(String string, int start) {
if (string.equals(this.string)) return false;
if (start == this.start) return false;
return true;
}
private static ImmutableSomething computeSomething(String string, int start) {
...
}
private static final CacheEntry[] cache = new CacheEntry[256];
private final String string;
private final int start;
private final ImmutableSomething something;
}
Аннотации приходят из lombok. Только представьте, что каждый делает то, что говорит его имя.
Целью является сохранение вызовов до computeSomething
, а также для минимизации распределения.
Кэширование не синхронизировано ни по локальной сети. Нет никакой гарантии, что один поток увидит обновления, сделанные другим. Это приемлемо. Также нет гарантии, что один поток не перезаписывает записи из другого. Это тоже приемлемо.
В небольшом тесте я написал, что это привело к хорошему ускорению по сравнению с sane caching alternatives. Моя забота о правильности: может ли когда-нибудь произойти, что поток видит недопустимую запись (например, один содержит неправильный something
)?
Это выглядит правильно для меня. Назначение ссылки объекта на переменную является атомной операцией, и вы не заботитесь об отсутствии гарантии видимости памяти, поэтому она выглядит нормально (за исключением очевидных проблем с компиляцией). –
@JBNizet Проблемы с компиляцией пропали. Я вижу, что писать что-нибудь немного больше без IDE - это плохая идея. – maaartinus