成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

@Transactional 與線程鎖:為何聯(lián)用會(huì)失效?

開(kāi)發(fā) 前端
很多小伙伴使用Spring事務(wù)時(shí),為了省事都喜歡使用@Transactional。但是@Transactional配合鎖,會(huì)導(dǎo)致一些預(yù)期之外的問(wèn)題!

很多小伙伴使用Spring事務(wù)時(shí),為了省事都喜歡使用@Transactional。但是@Transactional配合鎖,會(huì)導(dǎo)致一些預(yù)期之外的問(wèn)題!

在此舉例說(shuō)明。

數(shù)據(jù)準(zhǔn)備

我們將在該表中,實(shí)現(xiàn)level數(shù)據(jù)遞減的并發(fā)操作。

圖片圖片

Controller中,簡(jiǎn)單模擬10個(gè)線程各自執(zhí)行10次:

圖片圖片

@Transactional是如何導(dǎo)致鎖失效的

1、不加鎖

// service代碼
public void test() {
    // 簡(jiǎn)單的select + update 模擬業(yè)務(wù)場(chǎng)景
    Model model = mapper.choseOne("99");

 // 實(shí)現(xiàn) level -- 操作
    Model updater = new Model();
    updater.setId("99");
    updater.setLevel(model.getLevel() - 1);
    mapper.updateOne(updater);
}

執(zhí)行結(jié)果:我們發(fā)現(xiàn),level只扣減了26,說(shuō)明存在并發(fā)問(wèn)題!

圖片圖片

2、使用鎖

// service代碼
private Lock lock = new ReentrantLock();

public void test() {
try {
     //加鎖
     lock.lock();
     // 簡(jiǎn)單的select + update 模擬業(yè)務(wù)場(chǎng)景
     Model model = mapper.choseOne("99");

// 實(shí)現(xiàn) level -- 操作
     Model updater = new Model();
     updater.setId("99");
     updater.setLevel(model.getLevel() - 1);
     mapper.updateOne(updater);
 } finally {
       lock.unlock(); // 解鎖
    }
}

執(zhí)行結(jié)果:我們發(fā)現(xiàn),使用鎖是可以控制并發(fā)問(wèn)題。

圖片圖片

3、使用鎖+@Transactional

// service代碼
private Lock lock = new ReentrantLock();

@Transactional
public void test() {
try {
     //加鎖
     lock.lock();
     // 簡(jiǎn)單的select + update 模擬業(yè)務(wù)場(chǎng)景
     Model model = mapper.choseOne("99");

// 實(shí)現(xiàn) level -- 操作
     Model updater = new Model();
     updater.setId("99");
     updater.setLevel(model.getLevel() - 1);
     mapper.updateOne(updater);
 } finally {
       lock.unlock(); // 解鎖
    }
}

執(zhí)行結(jié)果:我們發(fā)現(xiàn),level只扣減了86!用了@Transactional之后,鎖怎么就失效了呢!

圖片圖片

4、問(wèn)題分析

我們都知道,@Transactional是通過(guò)使用AOP,在目標(biāo)方法執(zhí)行前后進(jìn)行事務(wù)的開(kāi)啟和提交。所以,Lock鎖住的代碼,其實(shí)并沒(méi)有包含住一整個(gè)事務(wù)!

通過(guò)下面的圖理解一下:

圖片圖片

當(dāng)線程A將level設(shè)置為99時(shí),此時(shí)鎖已經(jīng)釋放了,但是事務(wù)還沒(méi)提交!!線程B此時(shí)可以獲取到鎖并進(jìn)行查詢,查詢出來(lái)的level還是線程A修改之前的100,所以出現(xiàn)了并發(fā)問(wèn)題。

解決方案

1、@Transactional單獨(dú)一個(gè)方法

private Lock lock = new ReentrantLock();
@Transactional
public void test1() {
    // 簡(jiǎn)單的select + update 模擬業(yè)務(wù)場(chǎng)景
    Model model = mapper.choseOne("99");

// 實(shí)現(xiàn) level -- 操作
    Model updater = new Model();
    updater.setId("99");
    updater.setLevel(model.getLevel() - 1);
    mapper.updateOne(updater);
}

@Autowired
@Lazy
private CommonService commonService;
public void test() {
    try {
        // 加鎖
        lock.lock();
        // 自己注入自己,以使用到其代理類
        commonService.test1();
    } finally {
        lock.unlock(); // 解鎖
    }
}

執(zhí)行結(jié)果:沒(méi)有并發(fā)問(wèn)題出現(xiàn)!

圖片圖片

或者直接在controller層加鎖,也是一樣的道理。

2、使用編程式事務(wù)

// service代碼
private Lock lock = new ReentrantLock();
@Autowired
private PlatformTransactionManager transactionManager;
public void test() {
try {
     //加鎖
     lock.lock();
     // 編程式事務(wù)
        TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
        
     // 簡(jiǎn)單的select + update 模擬業(yè)務(wù)場(chǎng)景
     Model model = mapper.choseOne("99");

// 實(shí)現(xiàn) level -- 操作
     Model updater = new Model();
     updater.setId("99");
     updater.setLevel(model.getLevel() - 1);
     mapper.updateOne(updater);
     
// 在鎖中提交
        transactionManager.commit(status);
 } finally {
       lock.unlock(); // 解鎖
    }
}

執(zhí)行結(jié)果:我們發(fā)現(xiàn),將整個(gè)事務(wù)都鎖住,就沒(méi)問(wèn)題了!


圖片圖片

責(zé)任編輯:武曉燕 來(lái)源: 一安未來(lái)
相關(guān)推薦

2024-08-23 09:46:46

2022-09-20 22:27:08

事務(wù)失效public 修飾

2022-09-14 19:50:22

事務(wù)場(chǎng)景流程

2023-09-27 16:22:51

SpringMySQL原子性

2023-09-28 09:07:54

注解失效場(chǎng)景

2017-05-08 11:46:15

Java多線程

2017-05-31 14:03:07

Java多線程內(nèi)置鎖與顯示鎖

2022-08-09 09:34:32

Spring開(kāi)發(fā)

2022-08-08 17:38:45

Spring策略事務(wù)

2022-04-13 20:53:15

Spring事務(wù)管理

2021-04-14 15:17:08

Transaction代碼語(yǔ)言

2009-02-23 21:28:00

LinuxDrupal管理平臺(tái)

2015-07-20 09:35:57

開(kāi)源商業(yè)模式

2014-01-23 09:24:35

Windows 9

2024-10-14 16:25:59

C#線程鎖代碼

2020-08-26 08:59:58

Linux線程互斥鎖

2018-08-21 09:49:12

智慧城市

2023-09-08 08:52:12

Spring注解事務(wù)

2020-04-14 13:32:56

@Transacti失效場(chǎng)景

2023-08-29 10:51:44

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 日日夜夜精品 | 夜夜爽99久久国产综合精品女不卡 | 女生羞羞网站 | 国产精品成人久久久久 | 亚洲自拍偷拍欧美 | 日韩 欧美 综合 | 青青艹在线视频 | 久久精品国产a三级三级三级 | 激情六月丁香 | 精品美女 | 二区av| www.com久久久 | 国产原创在线观看 | av一级毛片 | 自拍在线 | 九九热这里只有精品6 | 最新一级毛片 | 99久久99| 亚洲欧洲成人av每日更新 | 香蕉超碰| 精品一区二区三区免费视频 | 久久99精品久久久久久 | 全部免费毛片在线播放网站 | www.9191| 在线不卡视频 | 久久精品欧美一区二区三区不卡 | 性一交一乱一透一a级 | 久久一区 | 国产精品激情在线 | 精品国产鲁一鲁一区二区张丽 | 国产精品一区二区在线免费观看 | 日韩视频在线免费观看 | 黄色a视频 | 亚洲一区在线观看视频 | 97在线观看 | 中文字幕视频在线 | 久草新视频 | 欧美视频二区 | 国产精品免费观看视频 | 国产亚洲精品精品国产亚洲综合 | 国产精品久久久亚洲 |