Sobes.tech
Back to questions
Senior
3

Как обеспечить потокобезопасность реализованного LRU-кэша?

Companies where asked
СовкомбанкСовкомбанк

Answer from AI

sobes.tech AI

Для обеспечения потокобезопасности LRU-кэша в Java можно использовать несколько подходов:

  1. Синхронизация методов — обернуть все методы, изменяющие состояние кэша, в synchronized-блоки или объявить их synchronized, чтобы только один поток мог выполнять операции одновременно.

  2. Использование ConcurrentHashMap и ConcurrentLinkedDeque — для хранения данных и порядка доступа, что позволит избежать блокировок на уровне всего кэша.

  3. Использование готовых потокобезопасных структур данных — например, LinkedHashMap с переопределённым методом removeEldestEntry можно обернуть в Collections.synchronizedMap, но при этом нужно дополнительно синхронизировать итерации.

  4. Использование 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 не будут выполняться одновременно из разных потоков, предотвращая состояние гонки.