1. 程式人生 > >悲觀鎖與樂觀鎖的故事

悲觀鎖與樂觀鎖的故事

旺財和小強生活在一個網上商城的系統中, 是一對兒執行緒好基友。 

星期一剛上班,旺財接到領導電話說,要把一個商品的庫存減少20, 旺財不敢怠慢,趕快把庫存取出來一看,哦,現在有1000個。

與此同時,小強也接到電話說要把同一商品的庫存減少30, 他一看,哦,現在有1000個。

旺財計算出最新的庫存值980, 儲存!

小強也計算出最新的庫存值970, 儲存 !  

旺財的資料被小強覆蓋了!

領導一看,本來賣出了50個商品,現在庫存只扣了30個,這樣持續下去就天下大亂了。 

旺財和小強, 各打二十大板, 長長記性!

小強說:“哥,要不我們還是想個辦法吧,再這樣下去要被打死的。”

旺財悲催地說: “這樣, 以後我們每次訪問庫存之前,都要先加鎖,加了鎖,就禁止別人再進入訪問,只能等待持有鎖的人來釋放。”

星期二, 領導讓旺財再次把庫存減少20 , 旺財這次萬分小心,先把庫存給鎖住,然後慢慢修改。 

小強也接到了把庫存減少的指令, 但是旺財哥已經把庫存鎖住了, 不能操作,小強只好去阻塞車間喝茶聊天,然後到就緒車間等待排程執行。 

好不容易等到可以再次執行了,小強一看,這庫存怎麼還鎖著呢!? 只好再次去阻塞車間喝茶。 

領導一看, 小強你怎麼回事, 老是喝茶聊天? !  還幹不幹活了?

小強爭辯說旺財哥一直鎖著庫存,我沒法操作。

領導不管這些, 把小強和旺財又打了二十大板。 

(備註: 這種加鎖的方式就是悲觀鎖了,悲觀鎖正如其名,每次取讀寫資料時候總認為資料會被別人修改,所以將資料加鎖,置於鎖定狀態, 不讓別人再訪問。缺點是如果持有鎖的時間太長,其他使用者需要等待很長時間。)

旺財說: “兄弟,這一次哥對不住你啊,處理得慢了一些, 不過哥剛才捱打的時候想了一個好辦法:樂觀鎖。”

小強說:“拉倒吧你,屁股都快被打爛了還樂觀?”

“你聽我說嘛, 我們在那個庫存欄位的旁邊,再加上一個版本(version)的欄位, 例如剛開始的時候(庫存= 1000, 版本=1), 每次你去讀的時候不僅要讀出庫存,還要讀出版本號, 等到你修改了庫存,往回寫的時候一定要檢查一下版本號,看看和你讀的時候是否一樣。”

“如果不一樣呢?”  小強問

“那就放棄這次寫的操作,重新讀取庫存和版本號, 重新來過。”

“如果一樣呢? ”

“那就放心大膽地把新的庫存值寫回去。把版本號也加1”

“我似乎有點明白了,我們試試,不過你要想好,我可不想再挨板子了。”

星期三, 旺財奉命把庫存減去30, 他先讀到了(庫存= 1000, 版本=1);  小強也要改庫存了,他要把庫存減去50, 於是他也讀到了(庫存= 1000, 版本=1)。 

旺財計算出新的庫存值970 ,寫回成功,現在版本變成了(庫存= 970, 版本=2)。 

小強也計算出新庫存950 , 也準備寫回,他戰戰兢兢地去看最新的版本號, 已經變成版本2了, 按照之前的約定,只好重新讀取了。

小強再次讀取(庫存= 970, 版本=2) , 計算出最新快取值920(970減去50), 再次試圖更新,沒想到又被別人搶了先,現在版本號已經變成3了 ,最新的資料是(庫存= 900, 版本= 3)。

唉, 只好重新來過, 計算出最新快取值850(900減去50),第三次終於更新成功了, 最新的庫存是 (庫存=850, 版本= 4)

領導看到旺財和小強忙得熱火朝天,一刻不停,並且庫存值也沒有亂掉, 滿意地點了點頭:好同志啊。

(備註: 這種方式就是所謂的樂觀鎖了,旺財和小強這次樂觀了一點,覺得一般情況下不會有太多人修改庫存,所以沒有加鎖,放心地去操作,只有在最後更新的時候才去看是否衝突。 這種方式適合於衝突不多的場景,如果衝突很多,資料爭用激烈,會導致不斷地嘗試,反而降低了效能。)