Eliminate synchronized block to avoid thread pinning in SingletonSupplier

This commit is contained in:
Yanming Zhou 2023-09-14 10:33:34 +08:00 committed by Juergen Hoeller
parent 09b1e5edf6
commit 46397381ba
1 changed files with 14 additions and 2 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,6 +16,8 @@
package org.springframework.util.function;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Supplier;
import org.springframework.lang.Nullable;
@ -31,6 +33,7 @@ import org.springframework.util.Assert;
* supplier for a method that returned {@code null} and caching the result.
*
* @author Juergen Hoeller
* @author Yanming Zhou
* @since 5.1
* @param <T> the type of results supplied by this supplier
*/
@ -45,6 +48,11 @@ public class SingletonSupplier<T> implements Supplier<T> {
@Nullable
private volatile T singletonInstance;
/**
* Guards access to write operations on the response.
*/
private final Lock writeLock = new ReentrantLock();
/**
* Build a {@code SingletonSupplier} with the given singleton instance
@ -90,7 +98,8 @@ public class SingletonSupplier<T> implements Supplier<T> {
public T get() {
T instance = this.singletonInstance;
if (instance == null) {
synchronized (this) {
this.writeLock.lock();
try {
instance = this.singletonInstance;
if (instance == null) {
if (this.instanceSupplier != null) {
@ -102,6 +111,9 @@ public class SingletonSupplier<T> implements Supplier<T> {
this.singletonInstance = instance;
}
}
finally {
this.writeLock.unlock();
}
}
return instance;
}