This is an automated email from the ASF dual-hosted git repository.

jianbin pushed a commit to branch 2.x
in repository https://gitbox.apache.org/repos/asf/incubator-seata.git


The following commit(s) were added to refs/heads/2.x by this push:
     new 49e99de508 optimize: replace synchronized with ReentrantLock in saga 
module (#8008)
49e99de508 is described below

commit 49e99de50891cbf31f630e75cea1814e2e1198b0
Author: somil jain <[email protected]>
AuthorDate: Fri Mar 20 13:53:03 2026 +0530

    optimize: replace synchronized with ReentrantLock in saga module (#8008)
---
 changes/en-us/2.x.md                                              | 2 ++
 .../seata/saga/engine/pcext/handlers/ChoiceStateHandler.java      | 5 ++++-
 .../engine/pcext/interceptors/ServiceTaskHandlerInterceptor.java  | 5 ++++-
 .../apache/seata/saga/engine/pcext/utils/CompensationHolder.java  | 5 ++++-
 .../org/apache/seata/saga/engine/pcext/utils/EngineUtils.java     | 5 ++++-
 .../apache/seata/saga/engine/pcext/utils/LoopContextHolder.java   | 5 ++++-
 .../org/apache/seata/saga/engine/pcext/utils/LoopTaskUtils.java   | 5 ++++-
 .../org/apache/seata/saga/engine/pcext/utils/ParameterUtils.java  | 7 +++++--
 .../seata/saga/engine/repo/impl/StateMachineRepositoryImpl.java   | 6 ++++--
 .../apache/seata/saga/proctrl/eventing/impl/DirectEventBus.java   | 5 ++++-
 .../seata/saga/engine/invoker/impl/SpringBeanServiceInvoker.java  | 8 ++++++--
 11 files changed, 45 insertions(+), 13 deletions(-)

diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md
index 0b7fc3ef40..e3fd0e1531 100644
--- a/changes/en-us/2.x.md
+++ b/changes/en-us/2.x.md
@@ -45,6 +45,7 @@ Add changes here for all PR submitted to the 2.x branch.
 - [[#7955](https://github.com/apache/incubator-seata/pull/7955)] change the 
getProperty call to resolvePlaceholders
 - [[#7971](https://github.com/apache/incubator-seata/pull/7971)] upgrade some 
dependencies
 - [[#7970](https://github.com/apache/incubator-seata/pull/7970)] Remove 
unnecessary refreshLeader from ClusterController cluster endpoint
+- [[#8008](https://github.com/apache/incubator-seata/pull/8008)] replace 
synchronized with ReentrantLock in saga module for Loom virtual thread 
compatibility
 - [[#8019](https://github.com/apache/incubator-seata/pull/8019)] mark 
deprecated JSON parsers
 
 
@@ -80,6 +81,7 @@ Thanks to these contributors for their code commits. Please 
report an unintended
 - [xingfudeshi](https://github.com/xingfudeshi)
 - [Sumit6307](https://github.com/Sumit6307)
 - [xiaoxiangyeyu0](https://github.com/xiaoxiangyeyu0)
+- [somiljain](https://github.com/somiljain)
 
 
 Also, we receive many valuable issues, questions and advices from our 
community. Thanks for you all.
diff --git 
a/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/handlers/ChoiceStateHandler.java
 
b/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/handlers/ChoiceStateHandler.java
index 9f6f05b73a..b89d2c184a 100644
--- 
a/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/handlers/ChoiceStateHandler.java
+++ 
b/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/handlers/ChoiceStateHandler.java
@@ -17,6 +17,7 @@
 package org.apache.seata.saga.engine.pcext.handlers;
 
 import org.apache.seata.common.exception.FrameworkErrorCode;
+import org.apache.seata.common.lock.ResourceLock;
 import org.apache.seata.common.util.StringUtils;
 import org.apache.seata.saga.engine.StateMachineConfig;
 import org.apache.seata.saga.engine.exception.EngineExecutionException;
@@ -42,6 +43,8 @@ import java.util.Map;
  */
 public class ChoiceStateHandler implements StateHandler {
 
+    private final ResourceLock CHOICE_LOCK = new ResourceLock();
+
     @Override
     public void process(ProcessContext context) throws 
EngineExecutionException {
 
@@ -50,7 +53,7 @@ public class ChoiceStateHandler implements StateHandler {
 
         Map<Object, String> choiceEvaluators = 
choiceState.getChoiceEvaluators();
         if (choiceEvaluators == null) {
-            synchronized (choiceState) {
+            try (ResourceLock ignored = CHOICE_LOCK.obtain()) {
                 choiceEvaluators = choiceState.getChoiceEvaluators();
                 if (choiceEvaluators == null) {
 
diff --git 
a/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/interceptors/ServiceTaskHandlerInterceptor.java
 
b/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/interceptors/ServiceTaskHandlerInterceptor.java
index bcbb498c6a..be34813435 100644
--- 
a/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/interceptors/ServiceTaskHandlerInterceptor.java
+++ 
b/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/interceptors/ServiceTaskHandlerInterceptor.java
@@ -18,6 +18,7 @@ package org.apache.seata.saga.engine.pcext.interceptors;
 
 import org.apache.seata.common.exception.FrameworkErrorCode;
 import org.apache.seata.common.loader.LoadLevel;
+import org.apache.seata.common.lock.ResourceLock;
 import org.apache.seata.common.util.CollectionUtils;
 import org.apache.seata.common.util.StringUtils;
 import org.apache.seata.saga.engine.StateMachineConfig;
@@ -61,6 +62,8 @@ public class ServiceTaskHandlerInterceptor implements 
StateHandlerInterceptor {
 
     private static final Logger LOGGER = 
LoggerFactory.getLogger(ServiceTaskHandlerInterceptor.class);
 
+    private final ResourceLock STATUS_LOCK = new ResourceLock();
+
     @Override
     public boolean match(Class<? extends InterceptableStateHandler> clazz) {
         return clazz != null
@@ -325,7 +328,7 @@ public class ServiceTaskHandlerInterceptor implements 
StateHandlerInterceptor {
 
                 Map<Object, String> statusEvaluators = 
state.getStatusEvaluators();
                 if (statusEvaluators == null) {
-                    synchronized (state) {
+                    try (ResourceLock ignored = STATUS_LOCK.obtain()) {
                         statusEvaluators = state.getStatusEvaluators();
                         if (statusEvaluators == null) {
                             statusEvaluators = new 
LinkedHashMap<>(statusMatchList.size());
diff --git 
a/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/utils/CompensationHolder.java
 
b/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/utils/CompensationHolder.java
index 9bae5c1153..dfb669a08c 100644
--- 
a/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/utils/CompensationHolder.java
+++ 
b/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/utils/CompensationHolder.java
@@ -17,6 +17,7 @@
 package org.apache.seata.saga.engine.pcext.utils;
 
 import org.apache.seata.common.exception.FrameworkErrorCode;
+import org.apache.seata.common.lock.ResourceLock;
 import org.apache.seata.common.util.CollectionUtils;
 import org.apache.seata.common.util.StringUtils;
 import org.apache.seata.saga.engine.exception.EngineExecutionException;
@@ -60,12 +61,14 @@ public class CompensationHolder {
      */
     private Stack<StateInstance> stateStackNeedCompensation = new Stack<>();
 
+    private static final ResourceLock HOLDER_LOCK = new ResourceLock();
+
     public static CompensationHolder getCurrent(ProcessContext context, 
boolean forceCreate) {
 
         CompensationHolder compensationholder =
                 (CompensationHolder) 
context.getVariable(DomainConstants.VAR_NAME_CURRENT_COMPENSATION_HOLDER);
         if (compensationholder == null && forceCreate) {
-            synchronized (context) {
+            try (ResourceLock ignored = HOLDER_LOCK.obtain()) {
                 compensationholder =
                         (CompensationHolder) 
context.getVariable(DomainConstants.VAR_NAME_CURRENT_COMPENSATION_HOLDER);
                 if (compensationholder == null) {
diff --git 
a/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/utils/EngineUtils.java
 
b/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/utils/EngineUtils.java
index be3a9ff783..6e319be3a6 100644
--- 
a/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/utils/EngineUtils.java
+++ 
b/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/utils/EngineUtils.java
@@ -16,6 +16,7 @@
  */
 package org.apache.seata.saga.engine.pcext.utils;
 
+import org.apache.seata.common.lock.ResourceLock;
 import org.apache.seata.common.util.CollectionUtils;
 import org.apache.seata.common.util.StringUtils;
 import org.apache.seata.saga.engine.AsyncCallback;
@@ -45,6 +46,8 @@ public class EngineUtils {
 
     private static final Logger LOGGER = 
LoggerFactory.getLogger(EngineUtils.class);
 
+    private static final ResourceLock EXCEPTION_LOCK = new ResourceLock();
+
     /**
      * generate parent id
      *
@@ -198,7 +201,7 @@ public class EngineUtils {
                 List<Class<? extends Exception>> exceptionClasses = 
exceptionMatch.getExceptionClasses();
                 if (CollectionUtils.isNotEmpty(exceptions)) {
                     if (exceptionClasses == null) {
-                        synchronized (exceptionMatch) {
+                        try (ResourceLock ignored = EXCEPTION_LOCK.obtain()) {
                             exceptionClasses = 
exceptionMatch.getExceptionClasses();
                             if (exceptionClasses == null) {
 
diff --git 
a/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/utils/LoopContextHolder.java
 
b/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/utils/LoopContextHolder.java
index 1335202641..0459ef47e2 100644
--- 
a/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/utils/LoopContextHolder.java
+++ 
b/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/utils/LoopContextHolder.java
@@ -16,6 +16,7 @@
  */
 package org.apache.seata.saga.engine.pcext.utils;
 
+import org.apache.seata.common.lock.ResourceLock;
 import org.apache.seata.saga.proctrl.ProcessContext;
 import org.apache.seata.saga.statelang.domain.DomainConstants;
 
@@ -38,12 +39,14 @@ public class LoopContextHolder {
     private final Stack<Integer> forwardCounterStack = new Stack<>();
     private Collection collection;
 
+    private static final ResourceLock CONTEXT_LOCK = new ResourceLock();
+
     public static LoopContextHolder getCurrent(ProcessContext context, boolean 
forceCreate) {
         LoopContextHolder loopContextHolder =
                 (LoopContextHolder) 
context.getVariable(DomainConstants.VAR_NAME_CURRENT_LOOP_CONTEXT_HOLDER);
 
         if (null == loopContextHolder && forceCreate) {
-            synchronized (context) {
+            try (ResourceLock ignored = CONTEXT_LOCK.obtain()) {
                 loopContextHolder =
                         (LoopContextHolder) 
context.getVariable(DomainConstants.VAR_NAME_CURRENT_LOOP_CONTEXT_HOLDER);
                 if (null == loopContextHolder) {
diff --git 
a/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/utils/LoopTaskUtils.java
 
b/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/utils/LoopTaskUtils.java
index 5208ad882c..a229fcd2c9 100644
--- 
a/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/utils/LoopTaskUtils.java
+++ 
b/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/utils/LoopTaskUtils.java
@@ -17,6 +17,7 @@
 package org.apache.seata.saga.engine.pcext.utils;
 
 import org.apache.seata.common.exception.FrameworkErrorCode;
+import org.apache.seata.common.lock.ResourceLock;
 import org.apache.seata.common.util.CollectionUtils;
 import org.apache.seata.common.util.NumberUtils;
 import org.apache.seata.common.util.StringUtils;
@@ -56,6 +57,8 @@ public class LoopTaskUtils {
 
     public static final String LOOP_STATE_NAME_PATTERN = "-loop-";
 
+    private static final ResourceLock LOOP_LOCK = new ResourceLock();
+
     /**
      * get Loop Config from State
      *
@@ -227,7 +230,7 @@ public class LoopTaskUtils {
                 currentLoopContext.getNrOfCompletedInstances().get();
 
         if (!currentLoopContext.isCompletionConditionSatisfied()) {
-            synchronized (currentLoopContext) {
+            try (ResourceLock ignored = LOOP_LOCK.obtain()) {
                 if (!currentLoopContext.isCompletionConditionSatisfied()) {
                     Map<String, Object> stateMachineContext =
                             (Map<String, Object>) 
context.getVariable(DomainConstants.VAR_NAME_STATEMACHINE_CONTEXT);
diff --git 
a/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/utils/ParameterUtils.java
 
b/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/utils/ParameterUtils.java
index 38f8204466..4c015827b1 100644
--- 
a/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/utils/ParameterUtils.java
+++ 
b/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/pcext/utils/ParameterUtils.java
@@ -16,6 +16,7 @@
  */
 package org.apache.seata.saga.engine.pcext.utils;
 
+import org.apache.seata.common.lock.ResourceLock;
 import org.apache.seata.common.util.CollectionUtils;
 import org.apache.seata.common.util.StringUtils;
 import org.apache.seata.saga.engine.expression.Expression;
@@ -36,6 +37,8 @@ import java.util.Map;
  */
 public class ParameterUtils {
 
+    private static final ResourceLock INPUT_LOCK = new ResourceLock();
+
     public static List<Object> createInputParams(
             ExpressionResolver expressionResolver,
             StateInstanceImpl stateInstance,
@@ -48,7 +51,7 @@ public class ParameterUtils {
 
         List<Object> inputExpressions = serviceTaskState.getInputExpressions();
         if (inputExpressions == null) {
-            synchronized (serviceTaskState) {
+            try (ResourceLock ignored = INPUT_LOCK.obtain()) {
                 inputExpressions = serviceTaskState.getInputExpressions();
                 if (inputExpressions == null) {
                     inputExpressions = new 
ArrayList<>(inputAssignments.size());
@@ -77,7 +80,7 @@ public class ParameterUtils {
 
         Map<String, Object> outputExpressions = 
serviceTaskState.getOutputExpressions();
         if (outputExpressions == null) {
-            synchronized (serviceTaskState) {
+            try (ResourceLock ignored = INPUT_LOCK.obtain()) {
                 outputExpressions = serviceTaskState.getOutputExpressions();
                 if (outputExpressions == null) {
                     outputExpressions = new 
LinkedHashMap<>(outputAssignments.size());
diff --git 
a/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/repo/impl/StateMachineRepositoryImpl.java
 
b/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/repo/impl/StateMachineRepositoryImpl.java
index 6ffdd9b83e..86e0ff65c0 100644
--- 
a/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/repo/impl/StateMachineRepositoryImpl.java
+++ 
b/saga/seata-saga-engine/src/main/java/org/apache/seata/saga/engine/repo/impl/StateMachineRepositoryImpl.java
@@ -16,6 +16,7 @@
  */
 package org.apache.seata.saga.engine.repo.impl;
 
+import org.apache.seata.common.lock.ResourceLock;
 import org.apache.seata.common.util.CollectionUtils;
 import org.apache.seata.common.util.StringUtils;
 import org.apache.seata.saga.engine.repo.StateMachineRepository;
@@ -44,6 +45,7 @@ import java.util.concurrent.ConcurrentHashMap;
 public class StateMachineRepositoryImpl implements StateMachineRepository {
 
     private static final Logger LOGGER = 
LoggerFactory.getLogger(StateMachineRepositoryImpl.class);
+    private final ResourceLock ITEM_LOCK = new ResourceLock();
     private Map<
                     String
                     /** Name_Tenant **/
@@ -66,7 +68,7 @@ public class StateMachineRepositoryImpl implements 
StateMachineRepository {
     public StateMachine getStateMachineById(String stateMachineId) {
         Item item = CollectionUtils.computeIfAbsent(stateMachineMapById, 
stateMachineId, key -> new Item());
         if (item.getValue() == null && stateLangStore != null) {
-            synchronized (item) {
+            try (ResourceLock ignored = ITEM_LOCK.obtain()) {
                 if (item.getValue() == null) {
                     StateMachine stateMachine = 
stateLangStore.getStateMachineById(stateMachineId);
                     if (stateMachine != null) {
@@ -92,7 +94,7 @@ public class StateMachineRepositoryImpl implements 
StateMachineRepository {
         Item item = CollectionUtils.computeIfAbsent(
                 stateMachineMapByNameAndTenant, stateMachineName + "_" + 
tenantId, key -> new Item());
         if (item.getValue() == null && stateLangStore != null) {
-            synchronized (item) {
+            try (ResourceLock ignored = ITEM_LOCK.obtain()) {
                 if (item.getValue() == null) {
                     StateMachine stateMachine = 
stateLangStore.getLastVersionStateMachine(stateMachineName, tenantId);
                     if (stateMachine != null) {
diff --git 
a/saga/seata-saga-processctrl/src/main/java/org/apache/seata/saga/proctrl/eventing/impl/DirectEventBus.java
 
b/saga/seata-saga-processctrl/src/main/java/org/apache/seata/saga/proctrl/eventing/impl/DirectEventBus.java
index 2f6c6f15f9..0e88229ada 100644
--- 
a/saga/seata-saga-processctrl/src/main/java/org/apache/seata/saga/proctrl/eventing/impl/DirectEventBus.java
+++ 
b/saga/seata-saga-processctrl/src/main/java/org/apache/seata/saga/proctrl/eventing/impl/DirectEventBus.java
@@ -17,6 +17,7 @@
 package org.apache.seata.saga.proctrl.eventing.impl;
 
 import org.apache.seata.common.exception.FrameworkException;
+import org.apache.seata.common.lock.ResourceLock;
 import org.apache.seata.common.util.CollectionUtils;
 import org.apache.seata.saga.proctrl.ProcessContext;
 import org.apache.seata.saga.proctrl.eventing.EventConsumer;
@@ -36,6 +37,8 @@ public class DirectEventBus extends 
AbstractEventBus<ProcessContext> {
 
     private static final String VAR_NAME_SYNC_EXE_STACK = 
"_sync_execution_stack_";
 
+    private final ResourceLock CONTEXT_LOCK = new ResourceLock();
+
     @Override
     public boolean offer(ProcessContext context) throws FrameworkException {
         List<EventConsumer> eventHandlers = 
getEventConsumers(context.getClass());
@@ -49,7 +52,7 @@ public class DirectEventBus extends 
AbstractEventBus<ProcessContext> {
         boolean isFirstEvent = false;
         Stack<ProcessContext> currentStack = (Stack<ProcessContext>) 
context.getVariable(VAR_NAME_SYNC_EXE_STACK);
         if (currentStack == null) {
-            synchronized (context) {
+            try (ResourceLock ignored = CONTEXT_LOCK.obtain()) {
                 currentStack = (Stack<ProcessContext>) 
context.getVariable(VAR_NAME_SYNC_EXE_STACK);
                 if (currentStack == null) {
                     currentStack = new Stack<>();
diff --git 
a/saga/seata-saga-spring/src/main/java/org/apache/seata/saga/engine/invoker/impl/SpringBeanServiceInvoker.java
 
b/saga/seata-saga-spring/src/main/java/org/apache/seata/saga/engine/invoker/impl/SpringBeanServiceInvoker.java
index b97cb064bf..922345a344 100644
--- 
a/saga/seata-saga-spring/src/main/java/org/apache/seata/saga/engine/invoker/impl/SpringBeanServiceInvoker.java
+++ 
b/saga/seata-saga-spring/src/main/java/org/apache/seata/saga/engine/invoker/impl/SpringBeanServiceInvoker.java
@@ -19,6 +19,7 @@ package org.apache.seata.saga.engine.invoker.impl;
 import org.apache.seata.common.exception.FrameworkErrorCode;
 import org.apache.seata.common.json.JsonSerializer;
 import org.apache.seata.common.json.JsonSerializerFactory;
+import org.apache.seata.common.lock.ResourceLock;
 import org.apache.seata.common.util.CollectionUtils;
 import org.apache.seata.saga.engine.exception.EngineExecutionException;
 import org.apache.seata.saga.engine.invoker.ServiceInvoker;
@@ -53,6 +54,9 @@ public class SpringBeanServiceInvoker implements 
ServiceInvoker, ApplicationCont
 
     private static final Logger LOGGER = 
LoggerFactory.getLogger(SpringBeanServiceInvoker.class);
 
+    private final ResourceLock METHOD_LOCK = new ResourceLock();
+    private final ResourceLock RETRY_LOCK = new ResourceLock();
+
     private ApplicationContext applicationContext;
     private ThreadPoolExecutor threadPoolExecutor;
     private String sagaJsonParser;
@@ -105,7 +109,7 @@ public class SpringBeanServiceInvoker implements 
ServiceInvoker, ApplicationCont
 
         Method method = state.getMethod();
         if (method == null) {
-            synchronized (state) {
+            try (ResourceLock ignored = METHOD_LOCK.obtain()) {
                 method = state.getMethod();
                 if (method == null) {
                     method = findMethod(bean.getClass(), 
state.getServiceMethod(), state.getParameterTypes());
@@ -196,7 +200,7 @@ public class SpringBeanServiceInvoker implements 
ServiceInvoker, ApplicationCont
                 } else {
                     List<Class<? extends Exception>> exceptionClasses = 
retryConfig.getExceptionClasses();
                     if (exceptionClasses == null) {
-                        synchronized (retryConfig) {
+                        try (ResourceLock ignored = RETRY_LOCK.obtain()) {
                             exceptionClasses = 
retryConfig.getExceptionClasses();
                             if (exceptionClasses == null) {
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to