Can LinkedHashMap(accessOrder=true) be guarded by ReadWriteLock ?

Remi Forax forax at univ-mlv.fr
Thu Nov 7 08:28:51 UTC 2024


----- Original Message -----
> From: "Andrey Turbanov" <turbanoff at gmail.com>
> To: "core-libs-dev" <core-libs-dev at openjdk.java.net>
> Sent: Thursday, November 7, 2024 9:17:00 AM
> Subject: Can LinkedHashMap(accessOrder=true) be guarded by ReadWriteLock ?

> Hello.
> I've got a question about LinkedHashMap created with accessOrder=true flag.
> Usually this constructor is used when we want to build LRU cache.
> https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/LinkedHashMap.html#<init>(int,float,boolean)
> 
>        LinkedHashMap<MyKey, MyValue> cache = new LinkedHashMap<>(8, 1f, true) {
>            @Override
>            protected boolean removeEldestEntry(Map.Entry<MyKey,
> MyValue> eldest) {
>                return size() > 32;
>            }
>        };
> 
> LinkedHashMap is not a thread-safe data structure, so to be able to
> use it in a concurrent environment, access to it should be guarded by
> some kind of synchronization.
> I often see in many projects that such access is guarded by
> ReentrantReadWriteLock.
> Example in OpenJDK:
> https://github.com/openjdk/jdk/blob/0e1c1b793d43064aabe9571057284899c9580f30/src/java.desktop/share/classes/sun/awt/image/ImageCache.java#L46
> 
> private final ReentrantReadWriteLock readWriteLock = new
> ReentrantReadWriteLock();
> 
> public MyValue get(MyKey key) {
>    readWriteLock.readLock().lock();
>    try {
>        return cache.get(key);
>    } finally {
>        readWriteLock.readLock().unlock();
>    }
> }
> 
> public void put(MyKey key, MyValue value) {
>    readWriteLock.writeLock().lock();
>    try {
>        cache.put(key, value);
>    } finally {
>        readWriteLock.writeLock().unlock();
>    }
> }
> 
> I can see in LHM javadoc that LinkedHashMap.get in such a case can
> cause structural modification:
> "In access-ordered linked hash maps, merely querying the map with get
> is a structural modification."
> 
> As I understand, it means that LinkedHashMap.get can't be guarded
> _just_ by ReadLock.
> Is my assumption correct?
> 
> Andrey Turbanov

Hello Andrey,
yes !

This flavor of LinkedHashMap has always been a little dubious because having a Map.get() that does a structural modification can be qualified at best as surprising, at worst as not compliant with the contract of Map.

regards,
Rémi


More information about the core-libs-dev mailing list