-
Notifications
You must be signed in to change notification settings - Fork 26.5k
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
Resolving the Thread - Safety Problem in registerReferenceKeyAndBeanName with Overloaded computeIfAbsent #15219
base: 3.3
Are you sure you want to change the base?
Conversation
public void registerReferenceKeyAndBeanName(String referenceKey, String referenceBeanNameOrAlias) { List<String> list = ConcurrentHashMapUtils.computeIfAbsent(referenceKeyMap, referenceKey, (key) -> new ArrayList<>()); if (!list.contains(referenceBeanNameOrAlias)) { list.add(referenceBeanNameOrAlias); // register bean name as alias referenceAliasMap.put(referenceBeanNameOrAlias, list.get(0)); } } ``` The ConcurrentHashMapUtils.computeIfAbsent method ensures the creation of a new list in a thread-safe manner when no list exists for the given referenceKey. However, the subsequent operations if (!list.contains(referenceBeanNameOrAlias)) and list.add(referenceBeanNameOrAlias) are not atomic. This situation can lead to thread-safety issues where multiple threads might simultaneously pass the contains check and then all perform the add operation, resulting in duplicate referenceBeanNameOrAlias entries within the list. To resolve this issue, I added an overloaded version of the computeIfAbsent method that allows for thread-safe operations on the value through the use of a Consumer<T> functional interface. Additionally, I provided concurrent unit tests: ConcurrentHashMapUtilsTest#threadSafetyOperatorForJava8Test ConcurrentHashMapUtilsTest#threadSafetyOperatorForJava17Test These tests confirm the correctness of the implementation.
…d pass automated checks.
…- version JDK environments.
…d pass automated checks.
…d pass automated checks.
…d pass automated checks. 😵
…d pass automated checks. 😭
Thank you very much for the screenshot 👍. Due to continuous errors when downloading local Maven dependencies, the project still cannot run mvn spotless:apply. Therefore, I have been trying to push my code to check if my code formatting passes the checks 😭. I will use your screenshot as a reference and try to reformat my code again. |
…d pass automated checks.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## 3.3 #15219 +/- ##
=============================================
- Coverage 60.79% 35.60% -25.19%
+ Complexity 10892 10881 -11
=============================================
Files 1885 1885
Lines 86082 86091 +9
Branches 12895 12895
=============================================
- Hits 52331 30657 -21674
- Misses 28303 50989 +22686
+ Partials 5448 4445 -1003
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
@AlbumenJ I'm not sure why the workflow execution timed out since my code changes should not affect the test runs of the AbstractDynamicConfigurationTest class. I suspect it might be due to dependent services. Could you please rerun the PR action? |
org.apache.dubbo.config.spring.reference.ReferenceBeanManager.java
The ConcurrentHashMapUtils.computeIfAbsent method ensures the creation of a new list in a thread-safe manner when no list exists for the given referenceKey. However, the subsequent operations if (!list.contains(referenceBeanNameOrAlias)) and list.add(referenceBeanNameOrAlias) are not atomic. This situation can lead to thread-safety issues where multiple threads might simultaneously pass the contains check and then all perform the add operation, resulting in duplicate referenceBeanNameOrAlias entries within the list.
To resolve this issue, I added an overloaded version of the computeIfAbsent method that allows for thread-safe operations on the value through the use of a Consumer functional interface. Additionally, I provided concurrent unit tests:
These tests confirm the correctness of the implementation.
The profile defined here cannot run the
spotless plugin
in JDK 8 because the version of the Spotless plugin is too high. Therefore, I've overridden the version of the Spotless plugin in the jdk8 - jdk11 profile to make it compatible with the lower - version environment.spotless plugin
version 2.22.0 can work properly in JDK versions ranging from 8 to 11.Use a lower version of the spotless-maven-plugin dependency to override the version defined by spotless-maven-plugin.version so as to support JDK 1.8.