Resolving the Thread-Safety Problem in registerReferenceKeyAndBeanName Using an Overloaded computeIfAbsent#15219
Resolving the Thread-Safety Problem in registerReferenceKeyAndBeanName Using an Overloaded computeIfAbsent#15219juzzia wants to merge 12 commits intoapache:3.3from
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 Report❌ 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 30655 -21676
- Misses 28303 50994 +22691
+ Partials 5448 4442 -1006
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? |
You can trigger it on your own Github Repo Actions like this, |
|
since the author doesn't respond for a long time, i submit a new pr #15258 |



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 pluginin 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 pluginversion 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.