業務場景:
模擬一個場景,給一個用戶的餘額充值。如果正常情況會出現什麼問題,併發下又會出現什麼問題,出現問題又怎麼解決,按照這個思路來講解下併發下的編程如何避免髒數據。
併發可能發生的情況,目前我接觸過兩大類:1.兩次改庫操作並發進來,只有一次有效。2.兩次一模一樣的請求進來,本應該修只改一次,結果修改了兩次。(第二種比第一種常見)
這是我們的表:
然後我們手動在數據庫添加一條數據,此時阿達這個用戶餘額爲0;
下面的是我們的接口,入參很簡單,傳用戶的id和要充值的錢。業務邏輯很簡單,先查一下用戶這個對象,然後把金額改變一下,最後入庫
這是測試方法:
①正常情況下:我們測試一下,分別運行一下兩方法
第一次充值:
第二次充值:
②模擬下併發,在接口的代碼裏讓線程休息5秒,這樣做是爲了讓第一次調用的線程,在改數據之前等下第二個線程。(併發的情況是同時進來的,並不好模擬。這裏我們投機一下,讓線程等待一下,這樣進來的兩個線程就跟併發的類似)
我們先把數據庫清下,讓餘額變成0。
看這兩次充錢是什麼反應
第一次充值:
第二次充值:
我們看下數據庫:
明明充了兩次錢800+600應該餘額1400.但我們的結果卻是600,這個就是併發造成的髒數據問題,是個很嚴重的bug。
解決方案:
1.加悲觀鎖用synchronized關鍵字
併發下,第一次充值:
第二次充值:
結果看到了,沒有充值錯誤。
2.樂觀鎖,給數據庫加個版本號
這樣修改會比對版本號如果版本號不對,就會修改失敗。
總結:
這篇文章主要是通過一個充錢的場景來模擬併發下對數據產生的影響,並給到悲觀鎖和樂觀鎖的解決方案。我是阿達,一名喜歡分享知識的程序員,時不時的也會荒腔走板的聊一聊電影、電視劇、音樂、漫畫,這裏已經有17位小夥伴在等你們啦,感興趣的就趕緊來點擊關注我把,哪裏有不明白或有不同觀點的地方歡迎留言。