AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當前位置:首頁 > 科技  > 軟件

詳解Spring多線程下如何保證事務的一致性

來源: 責編: 時間:2023-10-08 09:59:45 259觀看
導讀環境:Spring5.3.231. 事務原理首先,我們先來大概的了解下Spring事務的工作原理,核心技術是通過AOP實現,將獲取的Connection對象綁定到當前線程上下文中(ThreadLocal)。事務核心攔截器TransactionInterceptor對象,如下(以下

環境:Spring5.3.23ZK028資訊網——每日最新資訊28at.com

1. 事務原理

首先,我們先來大概的了解下Spring事務的工作原理,核心技術是通過AOP實現,將獲取的Connection對象綁定到當前線程上下文中(ThreadLocal)。ZK028資訊網——每日最新資訊28at.com

事務核心攔截器TransactionInterceptor對象,如下(以下只會列出核心代碼):ZK028資訊網——每日最新資訊28at.com

public class TransactionInterceptor {  public Object invoke(MethodInvocation invocation) {    // 該方法調用為核心方法,該方法在父類中    return invokeWithinTransaction(...) ;  }}

父類TransactionAspectSupport

public abstract class TransactionAspectSupport {  protected Object invokeWithinTransaction(...) {    // 1.1.創建事務對象    TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);    try {        // 調用下一個攔截器或者是目標方法      retVal = invocation.proceedWithInvocation();    }    catch (Throwable ex) {      // 1.2.回滾事務      completeTransactionAfterThrowing(txInfo, ex);      throw ex;    } finally {      // 重置ThreadLocal中的TransactionInfo對象      cleanupTransactionInfo(txInfo);    }    // 1.3.提交或者回滾事務    commitTransactionAfterReturning(txInfo);    return retVal;  }  }

上面代碼列出了主要的事務執行流程及動作,我們主要是關心數據庫連接對象Connection在當前線程中是如何使用的。ZK028資訊網——每日最新資訊28at.com

創建事務對象

protected TransactionInfo createTransactionIfNecessary(    @Nullable PlatformTransactionManager tm,    @Nullable TransactionAttribute txAttr,     final String joinpointIdentification) {  TransactionStatus status = null;  if (txAttr != null) {    if (tm != null) {      // 創建事務狀態對象      status = tm.getTransaction(txAttr);    }  }  // 將事務狀態對象包裝到TransactionInfo中,然后將這個對象綁定到當前線程中  return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);}

創建事務狀態對象

public abstract class AbstractPlatformTransactionManager {  public final TransactionStatus getTransaction(...) {    if (isExistingTransaction(transaction)) {      // Existing transaction found -> check propagation behavior to find out how to behave.      return handleExistingTransaction(def, transaction, debugEnabled);    }    // 如果超時時間 < -1則拋出異常    if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {      throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());    }    // 當前不存在事務,則拋出異常    if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {      throw new IllegalTransactionStateException(          "No existing transaction found for transaction marked with propagation 'mandatory'");    }    // 其它的傳播特性,開啟事務功能    else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||        def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||        def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {      try {        // 開始事務        return startTransaction(def, transaction, debugEnabled, suspendedResources);      }    }  }}

開始事務

private TransactionStatus startTransaction(    TransactionDefinition definition,     Object transaction,    boolean debugEnabled,     @Nullable SuspendedResourcesHolder suspendedResources) {  boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);  DefaultTransactionStatus status = newTransactionStatus(      definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);  //       doBegin(transaction, definition);  prepareSynchronization(status, definition);  return status;}

創建Connection對象,并綁定到當前線程ZK028資訊網——每日最新資訊28at.com

public class DataSourceTransactionManager {  protected void doBegin(      Object transaction,       TransactionDefinition definition) {    DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;    Connection con = null;    try {      if (!txObject.hasConnectionHolder() ||          txObject.getConnectionHolder().isSynchronizedWithTransaction()) {        // 獲取數據庫連接對象          Connection newCon = obtainDataSource().getConnection();        txObject.setConnectionHolder(new ConnectionHolder(newCon), true);      }      // 將連接對象綁定到當前的線程      if (txObject.isNewConnectionHolder()) {        TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());      }    }  }}

到此,已經清楚了當開始一個新的事務時,Spring會將獲取的Connection綁定到當前的Thread中。ZK028資訊網——每日最新資訊28at.com

當我們使用通過JdbcTemplate操作數據庫時,如下:ZK028資訊網——每日最新資訊28at.com

public class JdbcTemplate {  // 核心執行方法  private <T> T execute(...) {    // 獲取數據庫連接對象    Connection con = DataSourceUtils.getConnection(obtainDataSource());  }}

DataSourceUtilsZK028資訊網——每日最新資訊28at.com

public abstract class DataSourceUtils {  public static Connection getConnection(DataSource dataSource) throws CannotGetJdbcConnectionException {    try {      return doGetConnection(dataSource) ;    }  }  public static Connection doGetConnection(DataSource dataSource) throws SQLException {    // 通過TransactionSynchronizationManager從當前線程上下文中獲取連接對象    // 在上面我們也是通過這個對象將連接對象綁定到當前的Thread中    ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);    if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) {      conHolder.requested() ;      if (!conHolder.hasConnection()) {        conHolder.setConnection(fetchConnection(dataSource)) ;      }      return conHolder.getConnection() ;    }  }}

原理相信你應該非常清楚了,每個線程都會綁定自己的Connection。那在多線程下每個線程都使用的是自己的Connection對象,所以要想保證事務的一致性,單靠傳統的方式一個@Transaction是肯定無法解決的,接下來我們就來實現一個多線程下的事務一致性的處理。ZK028資訊網——每日最新資訊28at.com

2.多線程事務

多線程下要實現事務的一致性,我們需要借助JUC下的相關類來實現。ZK028資訊網——每日最新資訊28at.com

這里直接給出代碼示例:ZK028資訊網——每日最新資訊28at.com

static class PersonService {  @Resource  private JdbcTemplate jdbcTemplate;  @Resource  private DataSource dataSource ;   @Transactional  public void save() throws Exception {    CountDownLatch cdl = new CountDownLatch(2) ;    AtomicBoolean txRollback = new AtomicBoolean(false) ;    CompletableFuture.runAsync(() -> {      Person person = new Person();      person.setAge(1);      person.setName("張三");      transactionTemplate.execute(status -> {        int result = 0 ;        try {          result = jdbcTemplate.update("insert into t_person (age, name) values (?, ?)", person.getAge(), person.getName()) ;          // TODO          // System.out.println(1 / 0) ;        } catch (Exception e) {            // 當發生異常后將狀態該為true          txRollback.set(true) ;        }        try {            // 計數減一          cdl.countDown() ;          // 繼續等待其它線程結束          cdl.await() ;        } catch (InterruptedException e) {          e.printStackTrace();        }          // 如果回滾狀態為true說明有線程發生了異常,需要事務回滾        if (txRollback.get()) {          // 標記當前事務回滾          status.setRollbackOnly() ;        }        System.out.printf("%s Insert Operator Result: %d 次%n", Thread.currentThread().getName(), result);        return result ;      }) ;      }) ;    transactionTemplate.execute(status -> {      Person person = new Person();      person.setAge(2);      person.setName("李四");      int result = 0 ;      try {        result = jdbcTemplate.update("insert into t_person (age, name) values (?, ?)", person.getAge(), person.getName()) ;        // TODO        TimeUnit.SECONDS.sleep(3) ;      } catch (Exception e) {        txRollback.set(true) ;       }      try {        cdl.countDown() ;        cdl.await() ;      } catch (InterruptedException e) {        e.printStackTrace();      }      if (txRollback.get()) {        // 回滾        status.setRollbackOnly() ;      }      System.out.printf("%s Insert Operator Result: %d 次%n", Thread.currentThread().getName(), result);      return result ;    }) ;    cdl.await() ;    System.err.println("Operator Complete...") ;  }}

以上就是借助JUC來實現多線程下的事務一致性問題。ZK028資訊網——每日最新資訊28at.com

其實如果你真的理解了事務的原理,其實這里還有更加簡單的實現方式,大家可以先思考,咱們下期再說這種簡單的實現方法。ZK028資訊網——每日最新資訊28at.com

完畢!!!ZK028資訊網——每日最新資訊28at.com

本文鏈接:http://www.tebozhan.com/showinfo-26-12416-0.html詳解Spring多線程下如何保證事務的一致性

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 你真的理解Python Qt6基礎知識中的信號和槽機制嗎?

下一篇: Spring事務管理—快速入門

標簽:
  • 熱門焦點
  • MIX Fold3包裝盒泄露 新機本月登場

    小米的全新折疊屏旗艦MIX Fold3將于本月發布,近日該機的真機包裝盒在網上泄露。從圖上來看,新的MIX Fold3包裝盒在外觀設計方面延續了之前的方案,變化不大,這也是目前小米旗艦
  • K60至尊版剛預熱 一加Ace2 Pro正面硬剛

    Redmi這邊剛如火如荼的宣傳了K60 Ultra的各種技術和硬件配置,作為競品的一加也坐不住了。一加中國區總裁李杰發布了兩條微博,表示在自家的一加Ace2上早就已經采用了和PixelWo
  • 三言兩語說透設計模式的藝術-簡單工廠模式

    一、寫在前面工廠模式是最常見的一種創建型設計模式,通常說的工廠模式指的是工廠方法模式,是使用頻率最高的工廠模式。簡單工廠模式又稱為靜態工廠方法模式,不屬于GoF 23種設計
  • 一文看懂為蘋果Vision Pro開發應用程序

    譯者 | 布加迪審校 | 重樓蘋果的Vision Pro是一款混合現實(MR)頭戴設備。Vision Pro結合了虛擬現實(VR)和增強現實(AR)的沉浸感。其高分辨率顯示屏、先進的傳感器和強大的處理能力
  • Flowable工作流引擎的科普與實踐

    一.引言當我們在日常工作和業務中需要進行各種審批流程時,可能會面臨一系列技術和業務上的挑戰。手動處理這些審批流程可能會導致開發成本的增加以及業務復雜度的上升。在這
  • 一篇文章帶你了解 CSS 屬性選擇器

    屬性選擇器對帶有指定屬性的 HTML 元素設置樣式。可以為擁有指定屬性的 HTML 元素設置樣式,而不僅限于 class 和 id 屬性。一、了解屬性選擇器CSS屬性選擇器提供了一種簡單而
  • ESG的面子與里子

    來源 | 光子星球撰文 | 吳坤諺編輯 | 吳先之三伏大幕拉起,各地高溫預警不絕,但處于厄爾尼諾大&ldquo;烤&rdquo;之下的除了眾生,還有各大企業發布的ESG報告。ESG是&ldquo;環境保
  • iQOO 11S或7月上市:搭載“雞血版”驍龍8Gen2 史上最強5G Soc

    去年底,iQOO推出了“電競旗艦”iQOO 11系列,作為一款性能強機,iQOO 11不僅全球首發2K 144Hz E6全感屏,搭載了第二代驍龍8平臺及144Hz電競屏,同時在快充
  • 北京:科技教育體驗基地開始登記

      北京“科技館之城”科技教育體驗基地登記和認證工作日前啟動。首批北京科技教育體驗基地擬于2023年全國科普日期間掛牌,后續還將開展常態化登記。  北京科技教育體驗基
Top