1. 程式人生 > >JAVA併發程式設計:悲觀鎖與樂觀鎖

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問題~