欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

Synchronized鎖在Spring事務(wù)管理下,為啥還線程不安全?-創(chuàng)新互聯(lián)

大年初二,朋友問了我一個(gè)技術(shù)的問題(朋友實(shí)在是好學(xué),佩服!)

創(chuàng)新互聯(lián)是專業(yè)的網(wǎng)站建設(shè)公司,提供網(wǎng)站建設(shè),網(wǎng)站制作,網(wǎng)站設(shè)計(jì)等網(wǎng)站開發(fā)一體化解決方案;包括html5,成都小程序開發(fā),網(wǎng)站定制,企業(yè)網(wǎng)站建設(shè),購物商城網(wǎng)站建設(shè),成都響應(yīng)式網(wǎng)站建設(shè)公司,建網(wǎng)站,PHP網(wǎng)站建設(shè),軟件開發(fā),軟文營(yíng)銷,網(wǎng)站營(yíng)銷。歡迎做網(wǎng)站的企業(yè)前來合作洽談,創(chuàng)新互聯(lián)將竭誠為您服務(wù)!

開啟10000個(gè)線程,每個(gè)線程給員工表的money字段【初始值是0】加1,沒有使用悲觀鎖和樂觀鎖,但是在業(yè)務(wù)層方法上加了synchronized關(guān)鍵字,問題是代碼執(zhí)行完畢后數(shù)據(jù)庫中的money 字段不是10000,而是小于10000 問題出在哪里?

Service層代碼:
Synchronized鎖在Spring事務(wù)管理下,為啥還線程不安全?
SQL代碼(沒有加悲觀/樂觀鎖):
Synchronized鎖在Spring事務(wù)管理下,為啥還線程不安全?
用1000個(gè)線程跑代碼:
Synchronized鎖在Spring事務(wù)管理下,為啥還線程不安全?
簡(jiǎn)單來說:多線程跑一個(gè)使用synchronized關(guān)鍵字修飾的方法,方法內(nèi)操作的是數(shù)據(jù)庫,按正常邏輯應(yīng)該最終的值是1000,但經(jīng)過多次測(cè)試,結(jié)果是低于1000。這是為什么呢?

一、我的思考
既然測(cè)試出來的結(jié)果是低于1000,那說明這段代碼不是線程安全的。不是線程安全的,那問題出現(xiàn)在哪呢?眾所周知,synchronized方法能夠保證所修飾的代碼塊、方法保證有序性、原子性、可見性。

講道理,以上的代碼跑起來,問題中Service層的increaseMoney()是有序的、原子的、可見的,所以斷定跟synchronized應(yīng)該沒關(guān)系。既然Java層面上找不到原因,那分析一下數(shù)據(jù)庫層面的吧(因?yàn)榉椒▋?nèi)操作的是數(shù)據(jù)庫)。在increaseMoney()方法前加了@Transcational注解,說明這個(gè)方法是帶有事務(wù)的。事務(wù)能保證同組的SQL要么同時(shí)成功,要么同時(shí)失敗。講道理,如果沒有報(bào)錯(cuò)的話,應(yīng)該每個(gè)線程都對(duì)money值進(jìn)行+1。從理論上來說,結(jié)果應(yīng)該是1000的才對(duì)。
br/>既然Java層面上找不到原因,那分析一下數(shù)據(jù)庫層面的吧(因?yàn)榉椒▋?nèi)操作的是數(shù)據(jù)庫)。在increaseMoney()方法前加了@Transcational注解,說明這個(gè)方法是帶有事務(wù)的。事務(wù)能保證同組的SQL要么同時(shí)成功,要么同時(shí)失敗。講道理,如果沒有報(bào)錯(cuò)的話,應(yīng)該每個(gè)線程都對(duì)money值進(jìn)行+1。從理論上來說,結(jié)果應(yīng)該是1000的才對(duì)。

首先貼一下我的測(cè)試代碼:

@RestController
public class EmployeeController {

    @Autowired
    private EmployeeService employeeService;

    @RequestMapping("/add")
    public void addEmployee() {
        for (int i = 0; i < 1000; i++) {
            new Thread(() -> employeeService.addEmployee()).start();
        }
    }

}

@Service
public class EmployeeService {

    @Autowired
    private EmployeeRepository employeeRepository;

    @Transactional
    public synchronized void addEmployee() {

        // 查出ID為8的記錄,然后每次將年齡增加一
        Employee employee = employeeRepository.getOne(8);
        System.out.println(employee);
        Integer age = employee.getAge();
        employee.setAge(age + 1);

        employeeRepository.save(employee);
    }

}

簡(jiǎn)單地打印了每次拿到的employee值,并且拿到了SQL執(zhí)行的順序,如下(貼出小部分):
Synchronized鎖在Spring事務(wù)管理下,為啥還線程不安全?
從打印的情況我們可以得出:多線程情況下并沒有串行執(zhí)行addEmployee()方法。這就導(dǎo)致對(duì)同一個(gè)值做重復(fù)的修改,所以最終的數(shù)值比1000要少。

二、圖解出現(xiàn)的原因
發(fā)現(xiàn)并不是同步執(zhí)行的,于是我就懷疑synchronized關(guān)鍵字和Spring肯定有點(diǎn)沖突。于是根據(jù)這兩個(gè)關(guān)鍵字搜了一下,找到了問題所在。

我們知道Spring事務(wù)的底層是Spring AOP,而Spring AOP的底層是動(dòng)態(tài)代理技術(shù)。跟大家一起回顧一下動(dòng)態(tài)代理:

  public static void main(String[] args) {

        // 目標(biāo)對(duì)象
        Object target ;

        Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), Main.class, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                // 但凡帶有@Transcational注解的方法都會(huì)被攔截

                // 1... 開啟事務(wù)

                method.invoke(target);

                // 2... 提交事務(wù)

                return null;
            }

        });
    }

實(shí)際上Spring做的處理跟以上的思路是一樣的,我們可以看一下TransactionAspectSupport類中invokeWithinTransaction():

Synchronized鎖在Spring事務(wù)管理下,為啥還線程不安全?
調(diào)用方法前開啟事務(wù),調(diào)用方法后提交事務(wù)
Synchronized鎖在Spring事務(wù)管理下,為啥還線程不安全?
在多線程環(huán)境下,就可能會(huì)出現(xiàn):方法執(zhí)行完了(synchronized代碼塊執(zhí)行完了),事務(wù)還沒提交,別的線程可以進(jìn)入被synchronized修飾的方法,再讀取的時(shí)候,讀到的是還沒提交事務(wù)的數(shù)據(jù),這個(gè)數(shù)據(jù)不是最新的,所以就出現(xiàn)了這個(gè)問題。

Synchronized鎖在Spring事務(wù)管理下,為啥還線程不安全?
三、解決問題
從上面我們可以發(fā)現(xiàn),問題所在是因?yàn)锧Transcational注解和synchronized一起使用了,加鎖的范圍沒有包括到整個(gè)事務(wù)。所以我們可以這樣做:

新建一個(gè)名叫SynchronizedService類,讓其去調(diào)用addEmployee()方法,整個(gè)代碼如下:

@RestController
public class EmployeeController {

    @Autowired
    private SynchronizedService synchronizedService ;

    @RequestMapping("/add")
    public void addEmployee() {
        for (int i = 0; i < 1000; i++) {
            new Thread(() -> synchronizedService.synchronizedAddEmployee()).start();
        }
    }
}

// 新建的Service類
@Service
public class SynchronizedService {

    @Autowired
    private EmployeeService employeeService ;

    // 同步
    public synchronized void synchronizedAddEmployee() {
        employeeService.addEmployee();

    }
}

@Service
public class EmployeeService {

    @Autowired
    private EmployeeRepository employeeRepository;

    @Transactional
    public void addEmployee() {

        // 查出ID為8的記錄,然后每次將年齡增加一
        Employee employee = employeeRepository.getOne(8);
        System.out.println(Thread.currentThread().getName() + employee);
        Integer age = employee.getAge();
        employee.setAge(age + 1);

        employeeRepository.save(employee);

    }
}

我們將synchronized鎖的范圍包含到整個(gè)Spring事務(wù)上,這就不會(huì)出現(xiàn)線程安全的問題了。在測(cè)試的時(shí)候,我們可以發(fā)現(xiàn)1000個(gè)線程跑起來比之前要慢得多,當(dāng)然我們的數(shù)據(jù)是正確的:
Synchronized鎖在Spring事務(wù)管理下,為啥還線程不安全?
最后
可以發(fā)現(xiàn)的是,雖然說Spring事務(wù)用起來我們是非常方便的,但如果不了解一些Spring事務(wù)的細(xì)節(jié),很多時(shí)候出現(xiàn)Bug了就百思不得其解。還是得繼續(xù)加油努力呀~~~

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。

標(biāo)題名稱:Synchronized鎖在Spring事務(wù)管理下,為啥還線程不安全?-創(chuàng)新互聯(lián)
分享URL:http://chinadenli.net/article18/epjdp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供全網(wǎng)營(yíng)銷推廣電子商務(wù)、網(wǎng)站建設(shè)網(wǎng)站導(dǎo)航、自適應(yīng)網(wǎng)站標(biāo)簽優(yōu)化

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)頁設(shè)計(jì)公司
日韩综合国产欧美一区| 日本办公室三级在线观看| 老外那个很粗大做起来很爽| 大香蕉久久精品一区二区字幕| 日韩国产传媒在线精品| 日本深夜福利视频在线| 国产欧美日韩在线一区二区| 亚洲女同一区二区另类| 久久99热成人网不卡| 人妻少妇av中文字幕乱码高清| 麻豆亚州无矿码专区视频| 在线观看视频成人午夜| 美国女大兵激情豪放视频播放| 久草精品视频精品视频精品| 日韩在线中文字幕不卡| 日韩不卡一区二区在线| 五月婷婷综合缴情六月| 精品久久久一区二区三| 神马午夜福利免费视频| 亚洲国产精品av在线观看| 国产精品亚洲欧美一区麻豆| 国内胖女人做爰视频有没有| 亚洲国产精品久久琪琪| 男人和女人草逼免费视频| 伊人久久青草地婷婷综合| 久久少妇诱惑免费视频| 成人午夜视频精品一区| 国产精品视频一区二区秋霞| 熟女乱一区二区三区四区| 国产欧美日产中文一区| 久久精品偷拍视频观看| 日木乱偷人妻中文字幕在线| 大香蕉久久精品一区二区字幕| 国产又粗又猛又长又大| 国产精品大秀视频日韩精品| 精品久久综合日本欧美| 久久99一本色道亚洲精品| 熟女少妇一区二区三区蜜桃| 九九热最新视频免费观看| 久久碰国产一区二区三区| 日韩无套内射免费精品|