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

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

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

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

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

1. 事務原理

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

事務核心攔截器TransactionInterceptor對象,如下(以下只會列出核心代碼):huN28資訊網——每日最新資訊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在當前線程中是如何使用的。huN28資訊網——每日最新資訊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對象,并綁定到當前線程huN28資訊網——每日最新資訊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中。huN28資訊網——每日最新資訊28at.com

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

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

DataSourceUtilshuN28資訊網——每日最新資訊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是肯定無法解決的,接下來我們就來實現一個多線程下的事務一致性的處理。huN28資訊網——每日最新資訊28at.com

2.多線程事務

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

這里直接給出代碼示例:huN28資訊網——每日最新資訊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來實現多線程下的事務一致性問題。huN28資訊網——每日最新資訊28at.com

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

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

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

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

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

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

標簽:
  • 熱門焦點
  • 鴻蒙OS 4.0公測機型公布:甚至連nova6都支持

    華為全新的HarmonyOS 4.0操作系統將于今天下午正式登場,官方在發布會之前也已經正式給出了可升級的機型產品,這意味著這些機型會率先支持升級享用。這次的HarmonyOS 4.0支持
  • 一加Ace2 Pro真機揭曉 鈦空灰配色質感拉滿

    終于,在經過了幾波預熱之后,一加Ace2 Pro的外觀真機圖在網上出現了。還是博主數碼閑聊站曝光的,這次的外觀設計還是延續了一加11的方案,只是細節上有了調整,例如新加入了鈦空灰
  • 直屏旗艦來了 iQOO 12和K70 Pro同臺競技

    旗艦機基本上使用的都是雙曲面屏幕,這就讓很多喜歡直屏的愛好者在苦等一款直屏旗艦,這次,你們等到了。據博主數碼閑聊站帶來的最新爆料稱,Redmi下代旗艦K70 Pro和iQOO 12兩款手
  • 紅魔電競平板評測:大屏幕硬實力

    前言:三年的疫情因為要上網課的原因激活了平板市場,如今網課的時代已經過去,大家的生活都恢復到了正軌,這也就意味著,真正考驗平板電腦生存的環境來了。也就是面對著這種殘酷的
  • 小米平板5 Pro 12.4簡評:多專多能 兼顧影音娛樂的大屏利器

    疫情帶來了網課,網課盤活了安卓平板,安卓平板市場雖然中途停滯了幾年,但好的一點就是停滯的這幾年行業又有了新的發展方向,例如超窄邊框、高刷新率、多攝鏡頭組合等,這就讓安卓
  • 19個 JavaScript 單行代碼技巧,讓你看起來像個專業人士

    今天這篇文章跟大家分享18個JS單行代碼,你只需花幾分鐘時間,即可幫助您了解一些您可能不知道的 JS 知識,如果您已經知道了,就當作復習一下,古人云,溫故而知新嘛。現在,我們就開始今
  • 三分鐘白話RocketMQ系列—— 如何發送消息

    我們知道RocketMQ主要分為消息 生產、存儲(消息堆積)、消費 三大塊領域。那接下來,我們白話一下,RocketMQ是如何發送消息的,揭秘消息生產全過程。注意,如果白話中不小心提到相關代
  • 微軟邀請 Microsoft 365 商業用戶,測試視頻編輯器 Clipchamp

    8 月 1 日消息,微軟近日宣布即將面向 Microsoft 365 商業用戶,開放 Clipchamp 應用,邀請用戶通過該應用來編輯視頻。微軟于 2021 年收購 Clipchamp,隨后開始逐步整合到 Microsof
  • 本地生活這塊肥肉,拼多多也想吃一口

    出品/壹覽商業 作者/李彥編輯/木魚拼多多也看上本地生活這塊蛋糕了。近期,拼多多在App首頁&ldquo;充值中心&rdquo;入口上線了本機生活界面。壹覽商業發現,該界面目前主要
Top