spring-cloud / spring-cloud/spring-cloud-commons

LockedScopedProxyFactoryBean have some problems in heavy concurrency contention on ReadWriteLock

Open
#755 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
Java
Stars
751
Forks
744
Avg merge
1d 14h
Merged PRs (30d)
9

Description

Describe the bug
I found the scope of refresh bean will be destroied when a RefreshScopeRefreshedEvent calls, this operation will compete for the writelock of ReentrantReadWriteLock.
Wihle other reader threads access any method of this bean,they will compete for the readlock of the same ReentrantReadWriteLock.
If one reader threads which has the readlock is slow or dead cycle, when access this bean, at this time, one thread sends an RefreshScopeRefreshedEvent and trys to aquire writelock. Besides, a large mount of threads access some method of this bean, and these thread will be parked until the write-thread has been done.

I think the refresh of refresh scope bean shouldn't block other reader threads. Others can do their things on the previous bean instance.

Sample
I write a demo about this use of ReentrantReadWriteLock in this situation.

        ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
        Thread threadPark = new Thread(() -> {
            Lock readLock = lock.readLock();
            readLock.lock();
            try {
                while (true){
                    System.out.println("I have the read lock!! But I wan not to give it you");
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }finally {
                readLock.unlock();
            }
        });
        Thread threadWrite = new Thread(() -> {
            Lock writeLock = lock.writeLock();
            writeLock.lock();
            try {
                System.out.println("I have the write lock!!!!");
            }finally {
                writeLock.unlock();
            }
        });
        Thread threadRead = new Thread(() -> {
            Lock readLock = lock.readLock();
            readLock.lock();
            try {
                System.out.println("I have the read lock!!!!");
            }finally {
                readLock.unlock();
            }
        });
        threadPark.start();
        Thread.sleep(2000);
        threadWrite.start();
        Thread.sleep(2000);
        threadRead.start();

Solution
Can we use StampLock to replace the ReentrantReadWriteLock?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at LockedScopedProxyFactoryBean and the RefreshScopeRefreshedEvent path, then reproduce the contention with the ReentrantReadWriteLock sample in the issue. Investigate whether refresh can proceed without parking reader threads; done means the reported concurrency behavior is addressed and the relevant behavior is covered by a test.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.