樂觀鎖的兩種實現方式


什么場景下需要使用鎖?

在多節點部署或者多線程執行時,同一個時間可能有多個線程更新相同數據,產生沖突,這就是並發問題。這樣的情況下會出現以下問題:
更新丟失:一個事務更新數據后,被另一個更新數據的事務覆蓋。
臟讀:一個事務讀取另一個事物為提交的數據,即為臟讀。
其次還有幻讀。。
針對並發引入並發控制機制,即加鎖。
加鎖的目的是在同一個時間只有一個事務在更新數據,通過鎖獨占數據的修改權。

鎖的實現方式

          1、悲觀鎖,前提是,一定會有並發搶占資源,強行獨占資源,在整個數據處理過程中,將數據處於鎖定狀態。
          2、樂觀鎖,前提是,不會發生並發搶占資源,只有在提交操作的時候檢查是否違反數據完整性。只能防止臟讀后數據的提交,不能解決臟讀。
          當然,還有其他的鎖機制,暫時不多介紹,着重於樂觀鎖的實現。
          樂觀鎖,使用版本標識來確定讀到的數據與提交時的數據是否一致。提交后修改版本標識,不一致時可以采取丟棄和再次嘗試的策略。
           記錄1,id,status1,status2,stauts3,version,表示有三個不同的狀態,以及數據當前的版本
           操作1:update table set status1=1,status2=0,status3=0 where id=111;  
           操作2:update table set status1=0,status2=1,status3=0 where id=111;
           操作3:update table set status1=0,status2=0,status3=1 where id=111;
           沒有任何控制的情況下,順序執行3個操作,最后前兩個操作會被直接覆蓋。
           加上version字段,每一次的操作都會更新version,提交時如果version不匹配,停止本次提交,可以嘗試下一次的提交,以保證拿到的是操作1提交后的結果。
          這是一種經典的樂觀鎖實現。
          另外,java中的compareandswap即cas,解決多線程並行情況下使用鎖造成性能損耗的一種機制。
          CAS操作包含三個操作數,內存位置(V),預期原值(A)和新值(B)。如果內存位置的值與預期原值相匹配,那么處理器會西東將該位置值更新為新值。否則,處理器不做任何操作。
          記錄2: id,stauts,status 包含3種狀態值 1,2,3
           操作,update status=3 where id=111 and status=1;
           即 如果內存值為1,預期值為1,則修改新值。對於沒有執行的操作則丟棄。
          思考:這兩種方式有什么區別?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM