Performance: Using ReentrantLock instead of synchronized
diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/ext/RuntimeDelegate.java b/jaxrs-api/src/main/java/jakarta/ws/rs/ext/RuntimeDelegate.java index 3570e51..3dc71b8 100644 --- a/jaxrs-api/src/main/java/jakarta/ws/rs/ext/RuntimeDelegate.java +++ b/jaxrs-api/src/main/java/jakarta/ws/rs/ext/RuntimeDelegate.java
@@ -19,6 +19,8 @@ import java.lang.reflect.ReflectPermission; import java.net.URL; import java.util.concurrent.CompletionStage; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import jakarta.ws.rs.SeBootstrap; import jakarta.ws.rs.SeBootstrap.Instance; @@ -45,7 +47,7 @@ * {@link RuntimeDelegate#getInstance()}. */ public static final String JAXRS_RUNTIME_DELEGATE_PROPERTY = "jakarta.ws.rs.ext.RuntimeDelegate"; - private static final Object RD_LOCK = new Object(); + private static final Lock RD_LOCK = new ReentrantLock(); private static ReflectPermission suppressAccessChecksPermission = new ReflectPermission("suppressAccessChecks"); private static volatile RuntimeDelegate cachedDelegate; @@ -82,12 +84,15 @@ // Local variable is used to limit the number of more expensive accesses to a volatile field. RuntimeDelegate result = cachedDelegate; if (result == null) { // First check (no locking) - synchronized (RD_LOCK) { + RD_LOCK.lock(); + try { result = cachedDelegate; if (result == null) { // Second check (with locking) result = findDelegate(); cachedDelegate = result; } + } finally { + RD_LOCK.unlock(); } } return result; @@ -132,8 +137,11 @@ if (security != null) { security.checkPermission(suppressAccessChecksPermission); } - synchronized (RD_LOCK) { + RD_LOCK.lock(); + try { RuntimeDelegate.cachedDelegate = rd; + } finally { + RD_LOCK.unlock(); } }