1 問題描述
最近再做火車票購票時,在對票類庫存進行扣減,有執行緒安全的問題,遂加鎖lock進行同步,
但發現加鎖後並沒有控制住庫存執行緒安全的問題,導致庫存仍被超發。
先簡單介紹下,各層的技術架構:
中間層框架:springboot
持久層:mybatis
mvc框架:spring mvc
存在問題的**:
@transactional
@override
public list updatetables()
理論情況具體描述:
當庫存剩餘為1時,執行緒1拿到鎖進入同步**塊,扣減庫存,執行緒2等待鎖;
當執行緒1執行完同步**塊時,執行緒2拿到鎖,執行同步**塊,檢查到的庫存剩餘仍為0
2 排查問題
查詢資料發現spring的事務引起的,因為spring的@transactional是aop實現的,它是在函式開始前開啟事務,在函式執行完畢後提交事務。所以上面**中鎖的釋放是在事務提交之前,釋放鎖但是還未提交事務,所以另乙個事務緊跟著執行,該事務查詢的庫存是還未提交的老資料。
3 解決方法
因為能力有限,所以目前的解決方法是將判斷庫存和更新的**移動到controller中,不將他放在事務中,並且該**中不使用事務
4總結根據以上的排查過程,已經很清楚的確認了事務與鎖之間存在的問題。由於事務範圍大於鎖**塊範圍,在鎖**塊執行完成後,此時事務還未提交,導致此時進入鎖**塊的其他執行緒,讀到的仍是原有的庫存資料。
關於程式加鎖自己的一點見解:
(1)建議程式中盡量不要加鎖;
(2)如果使用鎖,盡可能使用分布式鎖
(3)使用鎖的過程中,盡量減小鎖粒度,盡量減小鎖的**範圍;
Spring 事務機制詳解
spring事務機制主要包括宣告式事務和程式設計式事務,此處側重講解宣告式事務,程式設計式事務在實際開發中得不到廣泛使用,僅供學習參考。spring 宣告式事務讓我們從複雜的事務處理中得到解脫。使得我們再也無需要去處理獲得連線 關閉連線 事務提交和回滾等這些操作。再也無需要我們在與事務相關的方法中處...
Spring事務傳播機制
在 spring的 transactiondefinition介面中一共定義了7種事務傳播屬性 propagation required 支援當前事務,如果當前沒有事務,就新建乙個事務。這是最常見的選擇,也是spring事務傳播機制的預設值。propagation supports 支援當前事務,如...
spring事務傳播機制
1.required 必須有乙個事務的支援。如果沒有事務,則新建立乙個,如果有父事務,則使用 fetch 父級事務 2.requires new 必定會建立乙個事務。如果有父事務,則掛起 suspend 父事務,等子事務執行完畢,在恢復 resume 父事務 3.supports 可以有或者沒有事務...