JAVA併發程式設計:悲觀鎖與樂觀鎖
生活
晴。
悲觀與樂觀的情緒概念
本篇來了解一下悲觀鎖和樂觀鎖,在瞭解這兩個鎖之前,我們首先有必要把悲觀和樂觀這兩個詞搞清楚:
悲觀:對世事懷有消極的看法,認為事物總往糟糕的方向發展。
樂觀:對世事懷有積極的態度,認為事物總往好的方向發展。
何為悲觀鎖
悲觀鎖:
假定會發生併發的衝突,因此遮蔽一切可能違反資料完整性的操作。
在整個資料處理過程中,鎖定要操作的資料。
悲觀鎖的實現(JAVA/資料庫)
悲觀鎖的實現方式:
JAVA:
synchronized /lock
資料庫:
mysql:
select … for update .
如果拿不到鎖就等待。
注意:mysql查詢掃描到的所有行都會被上行鎖,因此mysql在使用悲觀鎖時務必要用到索引,避免全表掃描,減少掃描行數。
oracle:
select … for update (no wait)
注意:oracle 的悲觀鎖 有一個no wait 的選項,即當獲取不到鎖時不等待直接返回。
樂觀鎖
樂觀鎖:
假定不會發生併發衝突,因此只在提交資料操作時才執行資料完整性一致性的檢查。
樂觀鎖不能解決髒讀。
樂觀鎖的體現(JAVA/資料庫)
樂觀鎖其實就是通過CAS不斷自旋,CAS即compareAndSwap:
執行函式:CAS(V,E,N)
V是要執行的變數,
E是期望值
N是新值。
當E不一致時說明有其他執行緒修改了該值,那麼該執行緒修改失敗,繼續CAS。直到成功。
樂觀鎖的實現:
JAVA:
原子類、AQS
資料庫:
SELECT … WHERE version = #version#
使用場景
樂觀鎖:適用於讀多寫少的場景。
悲觀鎖:適用於寫多讀少的場景。
實際如何選擇
需要結合這兩種鎖的特點,進行合理的選擇
-響應速度:選擇樂觀鎖。要麼衝突失敗要麼快速成功。悲觀鎖則需要等待釋放鎖才能被執行
-衝突頻率:頻率高的話不應選擇樂觀鎖,需要重試好幾次,代價大。而悲觀鎖保證成功率
-重試代價:若重試代價大則選擇悲觀鎖
後記
明天看下樂觀鎖下 CAS的ABA問題~