溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Springboot在有鎖的情況下怎么正確使用事務(wù)

發(fā)布時間:2021-12-17 16:06:25 來源:億速云 閱讀:153 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要介紹“Springboot在有鎖的情況下怎么正確使用事務(wù)”,在日常操作中,相信很多人在Springboot在有鎖的情況下怎么正確使用事務(wù)問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Springboot在有鎖的情況下怎么正確使用事務(wù)”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

1. 概述

老話說的好:想要賺錢,就去看看有錢人有什么需求,因為有錢人錢多,所以賺的多。

言歸正傳,在Java項目的研發(fā)中,“鎖”這個詞并不陌生,最經(jīng)典的使用場景是商品的超賣問題。

很多Java小白,通常會認為,給代碼加上一把“鎖”,就能解決多扣庫存問題,卻忽略了數(shù)據(jù)庫事務(wù)的問題,今天我們就來做一個實驗,分析一下商品超賣問題。

2. 場景介紹

有一款商品,庫存只剩1件。

購買商品時,做三個動作,一是檢查庫存,二是扣庫存,三是生成訂單,三個動作在一個事務(wù)中執(zhí)行。

模擬并發(fā)場景,使用10個線程同時執(zhí)行用戶購買商品的操作。

3. 代碼實現(xiàn)

3.1 不加鎖的代碼實現(xiàn)

@Transactional(rollbackFor = Exception.class)
    public void buy() {

        // 查看是商品否有庫存
        Integer count = getProductCount();
        if(count <= 0) {
            throw new RuntimeException("庫存為 0");
        }

        // 減庫存
        productRepository.reductCount();

        // 生成訂單
        createOrder();
    }

首先我們正常編寫業(yè)務(wù)邏輯,用 @Transactional 注解控制事務(wù)。

經(jīng)并發(fā)實驗,產(chǎn)生了超賣的現(xiàn)象。

3.2 加鎖的代碼實現(xiàn)

@Transactional(rollbackFor = Exception.class)
    public synchronized void buy() {

        // 查看是商品否有庫存
        Integer count = getProductCount();
        if(count <= 0) {
            throw new RuntimeException("庫存為 0");
        }

        // 減庫存
        productRepository.reductCount();

        // 生成訂單
        createOrder();
    }

這次我們使用 synchronized 關(guān)鍵字給方法加了把“鎖”,理論上應(yīng)該不會產(chǎn)生超賣現(xiàn)象了吧。

經(jīng)實驗,仍然產(chǎn)生了超賣現(xiàn)象。

因為雖然方法被鎖住了,可是@Transactional 注解并沒有及時的提交事務(wù),導(dǎo)致庫存沒有及時扣減為0,因此還是超賣了。

3.3 正確使用事務(wù)的代碼實現(xiàn)

@Autowired
    private PlatformTransactionManager platformTransactionManager;
    @Autowired
    private TransactionDefinition transactionDefinition;

    // @Transactional(rollbackFor = Exception.class)
    public synchronized void buy() {

        // 開啟事務(wù)
        TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);

        try {
            // 查看是商品否有庫存
            Integer count = getProductCount();
            if(count <= 0) {
                throw new RuntimeException("庫存為 0");
            }

            // 減庫存
            productRepository.reductCount();

            // 生成訂單
            createOrder();

            // 事務(wù)提交
            platformTransactionManager.commit(transactionStatus);
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            // 事務(wù)回滾
            platformTransactionManager.rollback(transactionStatus);
        }

    }

這次我們不使用@Transactional 注解管理事務(wù)了,改為手動管理事務(wù)。

經(jīng)實驗,解決了超賣現(xiàn)象。

到此,關(guān)于“Springboot在有鎖的情況下怎么正確使用事務(wù)”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI