You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by wu...@apache.org on 2023/05/30 06:04:43 UTC

[shardingsphere] branch master updated: Avoid ConcurrentHashMap recursive update in ShardingSphereServiceLoader.getServiceInstances (#24558)

This is an automated email from the ASF dual-hosted git repository.

wuweijie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new de53bbbcd2d Avoid ConcurrentHashMap recursive update in ShardingSphereServiceLoader.getServiceInstances (#24558)
de53bbbcd2d is described below

commit de53bbbcd2d5aa930ee408e4bc5119efe7041f50
Author: Hongsheng Zhong <zh...@apache.org>
AuthorDate: Tue May 30 14:04:35 2023 +0800

    Avoid ConcurrentHashMap recursive update in ShardingSphereServiceLoader.getServiceInstances (#24558)
    
    * Replace computeIfAbsent in getServiceInstances to avoid possible ConcurrentHashMap recursive update
    
    * Lazy load service instances to reduce locked time in getServiceInstances
    
    * Revert "Lazy load service instances to reduce locked time in getServiceInstances"
    
    This reverts commit 1352bd49462a8bf8ac77563958357aa4157e01d2.
    
    * Reduce lock range
---
 .../util/spi/ShardingSphereServiceLoader.java      | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/infra/util/src/main/java/org/apache/shardingsphere/infra/util/spi/ShardingSphereServiceLoader.java b/infra/util/src/main/java/org/apache/shardingsphere/infra/util/spi/ShardingSphereServiceLoader.java
index f52278f429e..a774defebe6 100644
--- a/infra/util/src/main/java/org/apache/shardingsphere/infra/util/spi/ShardingSphereServiceLoader.java
+++ b/infra/util/src/main/java/org/apache/shardingsphere/infra/util/spi/ShardingSphereServiceLoader.java
@@ -37,11 +37,21 @@ public final class ShardingSphereServiceLoader<T> {
     
     private static final Map<Class<?>, ShardingSphereServiceLoader<?>> LOADERS = new ConcurrentHashMap<>();
     
+    private static final int LOAD_LOCKS_COUNT = 16;
+    
+    private static final Object[] LOAD_LOCKS = new Object[LOAD_LOCKS_COUNT];
+    
     private final Class<T> serviceInterface;
     
     @Getter
     private final Collection<T> services;
     
+    static {
+        for (int i = 0; i < LOAD_LOCKS_COUNT; i++) {
+            LOAD_LOCKS[i] = new Object();
+        }
+    }
+    
     private ShardingSphereServiceLoader(final Class<T> serviceInterface) {
         this.serviceInterface = serviceInterface;
         validate();
@@ -72,7 +82,17 @@ public final class ShardingSphereServiceLoader<T> {
     @SuppressWarnings("unchecked")
     public static <T> Collection<T> getServiceInstances(final Class<T> serviceInterface) {
         ShardingSphereServiceLoader<?> result = LOADERS.get(serviceInterface);
-        return (Collection<T>) (null != result ? result.getServiceInstances() : LOADERS.computeIfAbsent(serviceInterface, ShardingSphereServiceLoader::new).getServiceInstances());
+        if (null != result) {
+            return (Collection<T>) result.getServiceInstances();
+        }
+        synchronized (LOAD_LOCKS[serviceInterface.hashCode() % LOAD_LOCKS_COUNT]) {
+            result = LOADERS.get(serviceInterface);
+            if (null == result) {
+                result = new ShardingSphereServiceLoader<>(serviceInterface);
+                LOADERS.put(serviceInterface, result);
+            }
+        }
+        return (Collection<T>) result.getServiceInstances();
     }
     
     private Collection<T> getServiceInstances() {