Browse Source

Use single volatile field for indicating pre-instantiation phase

See gh-34729
pull/35405/head
Juergen Hoeller 8 months ago
parent
commit
c4f66b776f
  1. 30
      spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java

30
spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java

@ -218,8 +218,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto @@ -218,8 +218,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
/** Whether bean definition metadata may be cached for all beans. */
private volatile boolean configurationFrozen;
private volatile boolean preInstantiationPhase;
/** Name prefix of main thread: only set during pre-instantiation phase. */
@Nullable
private volatile String mainThreadPrefix;
@ -1066,11 +1065,13 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto @@ -1066,11 +1065,13 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
@Override
@Nullable
protected Boolean isCurrentThreadAllowedToHoldSingletonLock() {
if (this.preInstantiationPhase) {
String mainThreadPrefix = this.mainThreadPrefix;
if (this.mainThreadPrefix != null) {
// We only differentiate in the preInstantiateSingletons phase.
PreInstantiation preInstantiation = this.preInstantiationThread.get();
if (preInstantiation != null) {
// A Spring-managed thread:
// A Spring-managed bootstrap thread:
// MAIN is allowed to lock (true) or even forced to lock (null),
// BACKGROUND is never allowed to lock (false).
return switch (preInstantiation) {
@ -1078,14 +1079,23 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto @@ -1078,14 +1079,23 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
case BACKGROUND -> false;
};
}
if (Boolean.FALSE.equals(this.strictLocking) ||
(this.strictLocking == null && !getThreadNamePrefix().equals(this.mainThreadPrefix))) {
// An unmanaged thread (assumed to be application-internal) with lenient locking,
// and not part of the same thread pool that provided the main bootstrap thread
// (excluding scenarios where we are hit by multiple external bootstrap threads).
// Not a Spring-managed bootstrap thread...
if (Boolean.FALSE.equals(this.strictLocking)) {
// Explicitly configured to use lenient locking wherever possible.
return true;
}
else if (this.strictLocking == null) {
// No explicit locking configuration -> infer appropriate locking.
if (mainThreadPrefix != null && !getThreadNamePrefix().equals(mainThreadPrefix)) {
// An unmanaged thread (assumed to be application-internal) with lenient locking,
// and not part of the same thread pool that provided the main bootstrap thread
// (excluding scenarios where we are hit by multiple external bootstrap threads).
return true;
}
}
}
// Traditional behavior: forced to always hold a full lock.
return null;
}
@ -1103,7 +1113,6 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto @@ -1103,7 +1113,6 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
// Trigger initialization of all non-lazy singleton beans...
List<CompletableFuture<?>> futures = new ArrayList<>();
this.preInstantiationPhase = true;
this.preInstantiationThread.set(PreInstantiation.MAIN);
this.mainThreadPrefix = getThreadNamePrefix();
try {
@ -1120,7 +1129,6 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto @@ -1120,7 +1129,6 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
finally {
this.mainThreadPrefix = null;
this.preInstantiationThread.remove();
this.preInstantiationPhase = false;
}
if (!futures.isEmpty()) {

Loading…
Cancel
Save