HHH-15541 Possible carrier thread pinning synchronized blocks migrated to ReentrantLock

This commit is contained in:
Khurelkhuyag 2023-12-15 11:42:45 +08:00
parent 67cdd0b28a
commit 93dc0aecf3
3 changed files with 167 additions and 94 deletions

View File

@ -109,10 +109,12 @@ public class StandardServiceRegistryImpl extends AbstractServiceRegistryImpl imp
* Not intended for general use. We need the ability to stop and "reactivate" a registry to allow
* experimentation with technologies such as GraalVM, Quarkus and Cri-O.
*/
public synchronized void resetAndReactivate(BootstrapServiceRegistry bootstrapServiceRegistry,
public void resetAndReactivate(BootstrapServiceRegistry bootstrapServiceRegistry,
List<StandardServiceInitiator<?>> serviceInitiators,
List<ProvidedService<?>> providedServices,
Map<?, ?> configurationValues) {
thisLock.lock();
try {
if ( super.isActive() ) {
throw new IllegalStateException( "Can't reactivate an active registry" );
}
@ -120,25 +122,43 @@ public class StandardServiceRegistryImpl extends AbstractServiceRegistryImpl imp
this.configurationValues = new HashMap( configurationValues );
super.reactivate();
applyServiceRegistrations( serviceInitiators, providedServices );
} finally {
thisLock.unlock();
}
}
@Override
public synchronized <R extends Service> R initiateService(ServiceInitiator<R> serviceInitiator) {
public <R extends Service> R initiateService(ServiceInitiator<R> serviceInitiator) {
thisLock.lock();
try {
// todo : add check/error for unexpected initiator types?
return ( (StandardServiceInitiator<R>) serviceInitiator ).initiateService( configurationValues, this );
} finally {
thisLock.unlock();
}
}
@Override
public synchronized <R extends Service> void configureService(ServiceBinding<R> serviceBinding) {
public <R extends Service> void configureService(ServiceBinding<R> serviceBinding) {
thisLock.lock();
try {
if ( serviceBinding.getService() instanceof Configurable ) {
( (Configurable) serviceBinding.getService() ).configure( configurationValues );
}
} finally {
thisLock.unlock();
}
}
@Override
public synchronized void destroy() {
public void destroy() {
thisLock.lock();
try {
super.destroy();
this.configurationValues = null;
} finally {
thisLock.unlock();
}
}
}

View File

@ -9,6 +9,8 @@ package org.hibernate.cache.spi;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.cache.CacheException;
@ -46,6 +48,7 @@ public abstract class AbstractRegionFactory implements RegionFactory {
private SessionFactoryOptions options;
protected final Lock thisLock = new ReentrantLock();
protected boolean isStarted() {
if ( started.get() ) {
@ -83,7 +86,8 @@ public abstract class AbstractRegionFactory implements RegionFactory {
@Override
public final void start(SessionFactoryOptions settings, Map<String,Object> configValues) throws CacheException {
if ( started.compareAndSet( false, true ) ) {
synchronized (this) {
thisLock.lock();
try {
this.options = settings;
try {
prepareForUse( settings, configValues );
@ -94,6 +98,8 @@ public abstract class AbstractRegionFactory implements RegionFactory {
started.set( false );
startingException = e;
}
} finally {
thisLock.unlock();
}
}
else {
@ -106,7 +112,8 @@ public abstract class AbstractRegionFactory implements RegionFactory {
@Override
public final void stop() {
if ( started.compareAndSet( true, false ) ) {
synchronized ( this ) {
thisLock.lock();
try {
try {
releaseFromUse();
}
@ -114,6 +121,8 @@ public abstract class AbstractRegionFactory implements RegionFactory {
options = null;
startingException = null;
}
} finally {
thisLock.unlock();
}
}
else {

View File

@ -14,6 +14,8 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import org.hibernate.boot.registry.BootstrapServiceRegistry;
@ -72,6 +74,9 @@ public abstract class AbstractServiceRegistryImpl
private final AtomicBoolean active = new AtomicBoolean( true );
protected final Lock thisLock = new ReentrantLock();
private final Lock serviceBindingListLock = new ReentrantLock();
protected AbstractServiceRegistryImpl(@Nullable ServiceRegistryImplementor parent) {
this( parent, true );
}
@ -199,7 +204,8 @@ public abstract class AbstractServiceRegistryImpl
}
//Any service initialization needs synchronization
synchronized ( this ) {
thisLock.lock();
try {
// Check again after having acquired the lock:
service = serviceRole.cast( initializedServiceByRole.get( serviceRole ) );
if ( service != null ) {
@ -219,13 +225,18 @@ public abstract class AbstractServiceRegistryImpl
initializedServiceByRole.put( serviceRole, service );
}
return service;
} finally {
thisLock.unlock();
}
}
protected <R extends Service> void registerService(ServiceBinding<R> serviceBinding, R service) {
serviceBinding.setService( service );
synchronized ( serviceBindingList ) {
serviceBindingListLock.lock();
try {
serviceBindingList.add( serviceBinding );
} finally {
serviceBindingListLock.unlock();
}
}
@ -351,13 +362,16 @@ public abstract class AbstractServiceRegistryImpl
}
@Override
public synchronized void destroy() {
public void destroy() {
thisLock.lock();
try {
if ( active.compareAndSet( true, false ) ) {
try {
//First thing, make sure that the fast path read is disabled so that
//threads not owning the synchronization lock can't get an invalid Service:
initializedServiceByRole.clear();
synchronized (serviceBindingList) {
serviceBindingListLock.lock();
try {
ListIterator<ServiceBinding<?>> serviceBindingsIterator = serviceBindingList.listIterator(
serviceBindingList.size()
);
@ -366,6 +380,8 @@ public abstract class AbstractServiceRegistryImpl
serviceBinding.getLifecycleOwner().stopService( serviceBinding );
}
serviceBindingList.clear();
} finally {
serviceBindingListLock.unlock();
}
serviceBindingMap.clear();
}
@ -375,10 +391,15 @@ public abstract class AbstractServiceRegistryImpl
}
}
}
} finally {
thisLock.unlock();
}
}
@Override
public synchronized <R extends Service> void stopService(ServiceBinding<R> binding) {
public <R extends Service> void stopService(ServiceBinding<R> binding) {
thisLock.lock();
try {
final Service service = binding.getService();
if ( service instanceof Stoppable ) {
try {
@ -388,10 +409,15 @@ public abstract class AbstractServiceRegistryImpl
log.unableToStopService( service.getClass(), e );
}
}
} finally {
thisLock.unlock();
}
}
@Override
public synchronized void registerChild(ServiceRegistryImplementor child) {
public void registerChild(ServiceRegistryImplementor child) {
thisLock.lock();
try {
if ( childRegistries == null ) {
childRegistries = new HashSet<>();
}
@ -401,10 +427,15 @@ public abstract class AbstractServiceRegistryImpl
child
);
}
} finally {
thisLock.unlock();
}
}
@Override
public synchronized void deRegisterChild(ServiceRegistryImplementor child) {
public void deRegisterChild(ServiceRegistryImplementor child) {
thisLock.lock();
try {
if ( childRegistries == null ) {
throw new IllegalStateException( "No child ServiceRegistry registrations found" );
}
@ -424,13 +455,18 @@ public abstract class AbstractServiceRegistryImpl
);
}
}
} finally {
thisLock.unlock();
}
}
/**
* Not intended for general use. We need the ability to stop and "reactivate" a registry to allow
* experimentation with technologies such as GraalVM, Quarkus and Cri-O.
*/
public synchronized void resetParent(@Nullable BootstrapServiceRegistry newParent) {
public void resetParent(@Nullable BootstrapServiceRegistry newParent) {
thisLock.lock();
try {
if ( this.parent != null ) {
this.parent.deRegisterChild( this );
}
@ -444,6 +480,9 @@ public abstract class AbstractServiceRegistryImpl
else {
this.parent = null;
}
} finally {
thisLock.unlock();
}
}
@Override
@ -477,10 +516,15 @@ public abstract class AbstractServiceRegistryImpl
* Not intended for general use. We need the ability to stop and "reactivate" a registry to allow
* experimentation with technologies such as GraalVM, Quarkus and Cri-O.
*/
public synchronized void reactivate() {
public void reactivate() {
thisLock.lock();
try {
if ( !active.compareAndSet( false, true ) ) {
throw new IllegalStateException( "Was not inactive, could not reactivate" );
}
} finally {
thisLock.unlock();
}
}
}