javalockingreentrantlockreentrantreadwritelock

Is ReentrantReadWriteLock implemented as a spin-lock?


How does ReentrantReadWriteLock work? Is it a spin-lock?

The question comes from Elasticsearch, when it shows

   java.lang.ThreadLocal$ThreadLocalMap.expungeStaleEntry(Unknown Source)
   java.lang.ThreadLocal$ThreadLocalMap.remove(Unknown Source)
   java.lang.ThreadLocal$ThreadLocalMap.access$200(Unknown Source)
   java.lang.ThreadLocal.remove(Unknown Source)
   java.util.concurrent.locks.ReentrantReadWriteLock$Sync.tryReleaseShared(Unknown Source)
   java.util.concurrent.locks.AbstractQueuedSynchronizer.releaseShared(Unknown Source)
   java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock.unlock(Unknown Source)

in hot threads in all snapshots and cpu usage is high at the same time. It looks like spin-lock.


Solution

  • There is a cost associated to thread local data. What you are seeing here is exactly this. You can even see a comment in ReentrantReadWriteLock mentionning this and optimizing it by caching the data of the thread local data:

    Comment:

        /**
         * The hold count of the last thread to successfully acquire
         * readLock. This saves ThreadLocal lookup in the common case
         * where the next thread to release is the last one to
         * acquire.
         * [...]
         */
        private transient HoldCounter cachedHoldCounter;
    

    ReentrantReadWriteLock does not use a spin-lock. It uses the Sync object which uses wait/notify (implemented by LockSupport.park(this)) from the AbstractQueueSynchronizer.