Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Dubbo-5987] Fix lock in DubboProtocol#getSharedClient #6018

Merged
merged 1 commit into from
Apr 12, 2021

Conversation

tangcent
Copy link
Contributor

@tangcent tangcent commented Apr 14, 2020

What is the purpose of the change

Brief changelog

  • The current lock mode
        locks.putIfAbsent(key, new Object());
        synchronized (locks.get(key)) {
                //do some thing
                //remove lock
                locks.remove(key);
        }
  • The situation which there is a problem:
    When thread A finishes executing locks.putIfAbsent(key, new Object()),
    another thread B which holding the lock executes locks.remove(key),
    and then thread A executes synchronized (locks.get(key)).

  • Attempt get lock by computeIfAbsent like this:

        synchronized (locks.computeIfAbsent(key, (k) -> new Object())) {
                try{
                        //do some thing
                } finally {
                        //remove lock
                        locks.remove(key);
            }
        }
  • The situation which there is a problem:
    1.When thread A finishes executing synchronized (locks.computeIfAbsent(key, (k) -> new Object())) create the lock LockA And synchronized ,
    2.Another thread B synchronized with LockA,
    3.Thread A executes locks.remove(key).
    4.Thread B hold the LockA And synchronized.
    5.Thread C executing synchronized (locks.computeIfAbsent(key, (k) -> new Object())) create the lock LockC And synchronized .
    -It seems difficult to remove a lock without any threads waiting for it exactly.

Verifying this change

Run test cases.

Follow this checklist to help us incorporate your contribution quickly and easily:

  • Make sure there is a GITHUB_issue field for the change (usually before you start working on it). Trivial changes like typos do not require a GITHUB issue. Your pull request should address just this issue, without pulling in other changes - one PR resolves one issue.
  • Format the pull request title like [Dubbo-XXX] Fix UnknownException when host config not exist #XXX. Each commit in the pull request should have a meaningful subject line and body.
  • Write a pull request description that is detailed enough to understand what the pull request does, how, and why.
  • Write necessary unit-test to verify your logic correction, more mock a little better when cross module dependency exist. If the new feature or significant change is committed, please remember to add sample in dubbo samples project.
  • Run mvn clean install -DskipTests=false & mvn clean test-compile failsafe:integration-test to make sure unit-test and integration-test pass.
  • If this contribution is large, please follow the Software Donation Guide.

@tangcent tangcent force-pushed the fix/#5987 branch 2 times, most recently from 57e7f59 to a5ec1d6 Compare April 15, 2020 00:02
@AlbumenJ
Copy link
Member

@tangcent hi, thanks for your contribution. Please reslove conficts with the latest master branch.

@tangcent
Copy link
Contributor Author

@AlbumenJ done

@AlbumenJ
Copy link
Member

I think this PR is related with #6102 and #6793. In latest version of master branch, there use a lock object existed permanently to avoid concurrency issues. I am wonder if the conection key will change for each request ? If no, shall we still use the same lock object for the same connect key even when the connect key changed this will cause some memory leak. Compare with the little momory leak, reduce lock object initialization and space recycling behavior maybe more significant ? Also, using synchronized for referenceClientMap will reduce the number of concurrent.

@tangcent How do you think?

@AlbumenJ AlbumenJ added the status/waiting-for-feedback Need reporters to triage label Feb 24, 2021
@tangcent
Copy link
Contributor Author

  • I think that the definition of the ReferenceClientMap means that it makes sense to cache the ReferenceClient.
    So most of the time the ReferenceClient will be found in the cache without triggering a lock operation.
    Does it make sense to keep a locker in memory for rarely triggered operations?

  • On the other hand. The most time consuming step is buildReferenceCountExchangeClient.
    So the only operation in synchronized (referenceClientMap) is put the PENDING_OBJECT .
    And then buildReferenceCountExchangeClient after jump out of the loop and release the lock(synchronized).
    It's my view that using synchronized for referenceClientMap here will reduce very few of concurrent.


vs #6793: reduce the memory usage
vs #6102: only reduce a few of concurrent

@AlbumenJ AlbumenJ merged commit 0f5040b into apache:master Apr 12, 2021
@AlbumenJ AlbumenJ added this to the 2.7.11 milestone Apr 12, 2021
AlbumenJ added a commit to AlbumenJ/dubbo that referenced this pull request May 28, 2021
@tangcent tangcent deleted the fix/#5987 branch February 28, 2023 09:55
vio-lin pushed a commit to vio-lin/incubator-dubbo that referenced this pull request Apr 18, 2023
(cherry picked from commit 0f5040b)

# Conflicts:
#	dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java
vio-lin added a commit to vio-lin/incubator-dubbo that referenced this pull request Apr 27, 2023
Fix lock in DubboProtocol#getSharedClient (apache#6018)

See merge request framework/dubbo!63
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status/waiting-for-feedback Need reporters to triage
Projects
None yet
Development

Successfully merging this pull request may close these issues.

What is the advantage of this lock?
2 participants