日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

五分钟学会悲观乐观锁-java vs mysql vs redis三种实现

發(fā)布時間:2025/4/5 数据库 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 五分钟学会悲观乐观锁-java vs mysql vs redis三种实现 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1 悲觀鎖樂觀鎖簡介

樂觀鎖( Optimistic Locking ) 相對悲觀鎖而言,樂觀鎖假設(shè)認為數(shù)據(jù)一般情況下不會造成沖突,所以在數(shù)據(jù)進行提交更新的時候,才會正式對數(shù)據(jù)的沖突與否進行檢測,如果發(fā)現(xiàn)沖突了,則讓返回用戶錯誤的信息,讓用戶決定如何去做。

悲觀鎖,正如其名,它指的是對數(shù)據(jù)被外界(包括本系統(tǒng)當前的其他事務(wù),以及來自外部系統(tǒng)的事務(wù)處理)修改持保守態(tài)度,因此,在整個數(shù)據(jù)處理過程中,將數(shù)據(jù)處于鎖定狀態(tài)。(百科)

最形象的悲觀鎖 vs 樂觀鎖

?

2.悲觀鎖樂觀鎖使用場景

兩種鎖各有優(yōu)缺點,不能單純的定義哪個好于哪個。樂觀鎖比較適合數(shù)據(jù)修改比較少,讀取比較頻繁的場景,即使出現(xiàn)了少量的沖突,這樣也省去了大量的鎖的開銷,故而提高了系統(tǒng)的吞吐量。但是如果經(jīng)常發(fā)生沖突(寫數(shù)據(jù)比較多的情況下),上層應(yīng)用不不斷的retry,這樣反而降低了性能,對于這種情況使用悲觀鎖就更合適。

3.Java中悲觀樂觀鎖實現(xiàn)

樂觀鎖:java中的樂觀鎖基本都是通過CAS操作實現(xiàn)的,CAS是一種更新的原子操作,比較當前值跟傳入值是否一樣,一樣則更新,否則失敗。以 java.util.concurrent 中的 AtomicInteger 為例,該類中原子操作保證了線程訪問的準確性。

getAndIncrement():獲取數(shù)據(jù)

import java.util.concurrent.atomic.AtomicInteger; public class JavaAtomic {public static void main(String[] args) throws InterruptedException {ProcessingThread pt = new ProcessingThread();Thread t1 = new Thread(pt, "t1");t1.start();Thread t2 = new Thread(pt, "t2");t2.start();t1.join();t2.join();System.out.println("Processing count=" + pt.getCount());} } class ProcessingThread implements Runnable {private AtomicInteger count = new AtomicInteger();@Overridepublic void run() {for (int i = 1; i < 5; i++) {processSomething(i);count.incrementAndGet();}}public int getCount() {return this.count.get();}private void processSomething(int i) {// processing some jobtry {Thread.sleep(i * 1000);} catch (InterruptedException e) {e.printStackTrace();}} }

?

compareAndSet(int expect, int update): 更新數(shù)據(jù)

import java.util.concurrent.atomic.AtomicInteger;public class Main {public static void main(String[] args){AtomicInteger atomicInteger = new AtomicInteger(100);boolean isSuccess = atomicInteger.compareAndSet(100,110); //current value 100 System.out.println(isSuccess); //true isSuccess = atomicInteger.compareAndSet(100,120); //current value 110 System.out.println(isSuccess); //false } }

?

利用JNI(Java Native Interface)來完成CPU指令的操作,訪問寄存器內(nèi)存數(shù)據(jù)進行數(shù)據(jù)訪問和設(shè)置

悲觀鎖:java中的悲觀鎖就是Synchronized,如單例模式所示

public class SingletonDemo {private static SingletonDemo instance = null;private SingletonDemo() { }public static synchronized SingletonDemo getInstance() {if (instance == null) {instance = new SingletonDemo ();}return instance;} }

?

樂觀鎖+悲觀鎖:AQS框架下的鎖則是先嘗試cas樂觀鎖去獲取鎖,獲取不到,才會轉(zhuǎn)換為悲觀鎖,如RetreenLock【http://ifeve.com/reentrantlock-and-fairness/】

public class ReentrantLockTest {private static Lock fairLock = new ReentrantLock(true);private static Lock unfairLock = new ReentrantLock();@Testpublic void fair() {System.out.println("fair version");for (int i = 0; i < 5; i++) {Thread thread = new Thread(new Job(fairLock));thread.setName("" + i);thread.start();}try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}}@Testpublic void unfair() {System.out.println("unfair version");for (int i = 0; i < 5; i++) {Thread thread = new Thread(new Job(unfairLock));thread.setName("" + i);thread.start();}try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}}private static class Job implements Runnable {private Lock lock;public Job(Lock lock) {this.lock = lock;}@Overridepublic void run() {for (int i = 0; i < 5; i++) {lock.lock();try {System.out.println("Lock by:"+ Thread.currentThread().getName());} finally {lock.unlock();}}}} }

?

4 數(shù)據(jù)庫悲觀鎖樂觀鎖的實現(xiàn)(以mysql為例)

悲觀鎖,使用事務(wù)實現(xiàn)

//0.開始事務(wù) begin;/begin work;/start transaction; (三者選一就可以) //1.查詢出商品信息 select status from t_goods where id=1 for update; //2.根據(jù)商品信息生成訂單 insert into t_orders (id,goods_id) values (null,1); //3.修改商品status為2 update t_goods set status=2; //4.提交事務(wù) commit;/commit work;

?

樂觀鎖

1.使用數(shù)據(jù)版本(Version)記錄機制實現(xiàn)

?

2.樂觀鎖定的第二種實現(xiàn)方式和第一種差不多,同樣是在需要樂觀鎖控制的table中增加一個字段,名稱無所謂,字段類型使用時間戳(timestamp), 和上面的version類似

5 nosql 悲觀鎖樂觀鎖的實現(xiàn)(以redis為例)

樂觀鎖使用watch

?

悲觀鎖使用事務(wù)

> MULTI OK > INCR foo QUEUED > INCR bar QUEUED > EXEC 1) (integer) 1 2) (integer) 1

?

6 總結(jié)

樂觀鎖機制采取了更加寬松的加鎖機制。悲觀鎖大多數(shù)情況下依靠數(shù)據(jù)庫的鎖機制實現(xiàn),以保證操作最大程度的獨占性。但隨之而來的就是數(shù)據(jù)庫 性能的大量開銷,特別是對長事務(wù)而言,這樣的開銷往往無法承受。相對悲觀鎖而言,樂觀鎖更傾向于開發(fā)運用。【百科】

參考資料

【1】https://chenzhou123520.iteye.com/blog/1860954

【2】https://chenzhou123520.iteye.com/blog/1863407

【3】https://blog.csdn.net/skycnlr/article/details/85689582

【4】https://www.journaldev.com/1095/atomicinteger-java

【5】https://howtodoinjava.com/java/multi-threading/atomicinteger-example/

【6】https://developpaper.com/transaction-mechanism-and-optimistic-lock-implementation-in-redis/

轉(zhuǎn)載于:https://www.cnblogs.com/davidwang456/p/11383525.html

總結(jié)

以上是生活随笔為你收集整理的五分钟学会悲观乐观锁-java vs mysql vs redis三种实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。