樂觀鎖的兩種實現方式
阿新 • • 發佈:2019-02-18
什麼場景下需要使用鎖?
在多節點部署或者多執行緒執行時,同一個時間可能有多個執行緒更新相同資料,產生衝突,這就是併發問題。這樣的情況下會出現以下問題: 更新丟失:一個事務更新資料後,被另一個更新資料的事務覆蓋。 髒讀:一個事務讀取另一個事物為提交的資料,即為髒讀。 其次還有幻讀。。 針對併發引入併發控制機制,即加鎖。 加鎖的目的是在同一個時間只有一個事務在更新資料,通過鎖獨佔資料的修改權。鎖的實現方式
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,則修改新值。對於沒有執行的操作則丟棄。 思考:這兩種方式有什麼區別?