mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-17 16:39:29 +00:00
Revise volatile access to singletonInstance field
For defensiveness against a singletonInstance/initialized visibility mismatch, we accept the locking overhead for pre-initialized null values (where we need the initialized field) in favor of a defensive fast path for non-null values (where we only need the singletonInstance field). Closes gh-35905
This commit is contained in:
@@ -47,12 +47,13 @@ public class SingletonSupplier<T extends @Nullable Object> implements Supplier<T
|
||||
|
||||
private volatile @Nullable T singletonInstance;
|
||||
|
||||
private volatile boolean initialized;
|
||||
private boolean initialized;
|
||||
|
||||
/**
|
||||
* Guards access to write operations on the {@code singletonInstance} field.
|
||||
* Guards access to write operations on the {@code singletonInstance} and
|
||||
* {@code initialized} fields.
|
||||
*/
|
||||
private final Lock writeLock = new ReentrantLock();
|
||||
private final Lock initializationLock = new ReentrantLock();
|
||||
|
||||
|
||||
/**
|
||||
@@ -99,8 +100,12 @@ public class SingletonSupplier<T extends @Nullable Object> implements Supplier<T
|
||||
@Override
|
||||
public @Nullable T get() {
|
||||
T instance = this.singletonInstance;
|
||||
if (!this.initialized) {
|
||||
this.writeLock.lock();
|
||||
if (instance == null) {
|
||||
// Either not initialized yet, or a pre-initialized null value ->
|
||||
// specific determination follows within full initialization lock.
|
||||
// Pre-initialized null values are rare, so we accept the locking
|
||||
// overhead in favor of a defensive fast path for non-null values.
|
||||
this.initializationLock.lock();
|
||||
try {
|
||||
instance = this.singletonInstance;
|
||||
if (!this.initialized) {
|
||||
@@ -115,7 +120,7 @@ public class SingletonSupplier<T extends @Nullable Object> implements Supplier<T
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this.writeLock.unlock();
|
||||
this.initializationLock.unlock();
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
|
||||
Reference in New Issue
Block a user