樂觀鎖的使用場景

樂觀鎖是一種輕量級鎖,在併發競爭不激烈的場景下,我們可以使用樂觀鎖來保證線程安全。

我們來看一個場景:定時job如何做併發控制,保證只有一臺服務器執行?

這個場景其實很適合使用樂觀鎖,因爲我們的跑job的服務器節點不會太多,可能就幾臺,幾十臺。

如何使用呢?我們可以參考一下CAS的實現。

首先每條job都會配置在數據庫中,初始狀態是N,如果有job開始跑了,會先把狀態置爲Y。

併發場景我們是這樣考慮的,拿預期值和修改值去更新這條數據,sql是這樣的:

 

 

 

 

 

 

 

update 
    job_table jt
set
    jt.status = 'Y',
    jt.update_date = sysdate
where
    jt.job_code = 'job_a_code' and
    jt.status = 'N'

 

這裏做一下簡單說明:

首先,我們有一個期望值N,也就是說,只有期望值是N,我纔會去修改job的狀態字段。

這個期望值,我們可以理解成CAS中的內存值。

然後呢?CAS還有一個修改值,也就是我們傳過來的Y,我們把狀態字段置爲Y,告訴其他線程,這個job已經在跑了。

CAS還有一個原始值,也就是我們這裏的入參N。注意這裏的原始值和期望值的區別。

 

OK,完美,三個值都有了,

期望值N

修改值Y

原始值N

接下來就是使用CAS來進行併發控制了。

如果線程A和線程B同時過來了,都要修改job的狀態字段,由於我們在應用層沒有加鎖,這兩個線程同時到達了數據庫,

如果我們採用oracle/mysql的默認隔離級別的話,那麼因爲是修改同一條數據,數據庫會加鎖,也就是說這2個請求會

排隊,依次執行。假設線程B先執行了,然後線程A去執行的時候,發現期望值是Y,不符合預期,那麼線程A就會認爲有

其他線程修改了job字段的值,這時候線程A修改失敗,直接返回了。

 

然後在應用層面,我們可以根據我們的update語句的返回值,來判斷,如果修改成功了,那麼update語句返回的值是1,

也就是修改了一條記錄。這是我認爲我成功的獲得了job鎖,接着開始執行job。否則,update語句返回的值是0,獲取鎖失敗,直接退出job。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章