Как обеспечить потокобезопасность реализованного LRU-кэша?
Ответ от нейросети
sobes.tech AI
Для обеспечения потокобезопасности LRU-кэша в Java можно использовать несколько подходов:
-
Синхронизация методов — обернуть все методы, изменяющие состояние кэша, в synchronized-блоки или объявить их synchronized, чтобы только один поток мог выполнять операции одновременно.
-
Использование ConcurrentHashMap и ConcurrentLinkedDeque — для хранения данных и порядка доступа, что позволит избежать блокировок на уровне всего кэша.
-
Использование готовых потокобезопасных структур данных — например,
LinkedHashMapс переопределённым методомremoveEldestEntryможно обернуть вCollections.synchronizedMap, но при этом нужно дополнительно синхронизировать итерации. -
Использование
ReentrantLock— более гибкий механизм блокировок, позволяющий контролировать доступ и избегать проблем с производительностью.
Пример с synchronized методом:
public class ThreadSafeLRUCache<K, V> {
private final int capacity;
private final LinkedHashMap<K, V> cache;
public ThreadSafeLRUCache(int capacity) {
this.capacity = capacity;
this.cache = new LinkedHashMap<K, V>(capacity, 0.75f, true) {
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > ThreadSafeLRUCache.this.capacity;
}
};
}
public synchronized V get(K key) {
return cache.get(key);
}
public synchronized void put(K key, V value) {
cache.put(key, value);
}
}
Такой подход гарантирует, что операции get и put не будут выполняться одновременно из разных потоков, предотвращая состояние гонки.