<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當(dāng)前位置: 首頁 - 科技 - 知識(shí)百科 - 正文

        悲觀鎖和樂觀鎖的比較和使用

        來源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-09 16:26:39
        文檔

        悲觀鎖和樂觀鎖的比較和使用

        悲觀鎖和樂觀鎖的比較和使用:悲觀鎖(Pessimistic Lock) 顧名思義,就是 很悲觀 ,每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人會(huì)修改,所以每次在拿數(shù)據(jù)的時(shí)候都會(huì)上鎖,這樣別人想拿這個(gè)數(shù)據(jù)就會(huì)block直到它拿到鎖。傳統(tǒng)的關(guān)系型數(shù)據(jù)庫里邊就用到了很多這種鎖機(jī)制,比如行鎖,表鎖等,讀鎖,寫鎖等,
        推薦度:
        導(dǎo)讀悲觀鎖和樂觀鎖的比較和使用:悲觀鎖(Pessimistic Lock) 顧名思義,就是 很悲觀 ,每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人會(huì)修改,所以每次在拿數(shù)據(jù)的時(shí)候都會(huì)上鎖,這樣別人想拿這個(gè)數(shù)據(jù)就會(huì)block直到它拿到鎖。傳統(tǒng)的關(guān)系型數(shù)據(jù)庫里邊就用到了很多這種鎖機(jī)制,比如行鎖,表鎖等,讀鎖,寫鎖等,

        悲觀鎖(Pessimistic Lock) 顧名思義,就是 很悲觀 ,每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人會(huì)修改,所以每次在拿數(shù)據(jù)的時(shí)候都會(huì)上鎖,這樣別人想拿這個(gè)數(shù)據(jù)就會(huì)block直到它拿到鎖。傳統(tǒng)的關(guān)系型數(shù)據(jù)庫里邊就用到了很多這種鎖機(jī)制,比如行鎖,表鎖等,讀鎖,寫鎖等,

        悲觀鎖(Pessimistic Lock)

        顧名思義,就是很悲觀,每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人會(huì)修改,所以每次在拿數(shù)據(jù)的時(shí)候都會(huì)上鎖,這樣別人想拿這個(gè)數(shù)據(jù)就會(huì)block直到它拿到鎖。傳統(tǒng)的關(guān)系型數(shù)據(jù)庫里邊就用到了很多這種鎖機(jī)制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。

        我們認(rèn)為系統(tǒng)中的并發(fā)更新會(huì)非常頻繁,并且事務(wù)失敗了以后重來的開銷很大,這樣以來,我們就需要采用真正意義上的鎖來進(jìn)行實(shí)現(xiàn)。悲觀鎖的基本思想就是每次一個(gè)事務(wù)讀取某一條記錄后,就會(huì)把這條記錄鎖住,這樣其它的事務(wù)要想更新,必須等以前的事務(wù)提交或者回滾解除鎖。

        實(shí)現(xiàn)方式:

        大多在數(shù)據(jù)庫層面實(shí)現(xiàn)加鎖操作,JDBC方式:在JDBC中使用悲觀鎖,需要使用select for update語句,e.g.

        Select * from Account 
        where ...(where condition).. for update

        樂觀鎖(Optimistic Lock)

        顧名思義,就是很樂觀,每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人不會(huì)修改,所以不會(huì)上鎖,但是在更新的時(shí)候會(huì)判斷一下在此期間別人有沒有去更新這個(gè)數(shù)據(jù),可以使用版本號(hào)等機(jī)制。樂觀鎖適用于多讀的應(yīng)用類型,這樣可以提高吞吐量,像數(shù)據(jù)庫如果提供類似于write_condition機(jī)制的其實(shí)都是提供的樂觀鎖。

        我們認(rèn)為系統(tǒng)中的事務(wù)并發(fā)更新不會(huì)很頻繁,即使沖突了也沒事,大不了重新再來一次。它的基本思想就是每次提交一個(gè)事務(wù)更新時(shí),我們想看看要修改的東西從上次讀取以后有沒有被其它事務(wù)修改過,如果修改過,那么更新就會(huì)失敗。

        實(shí)現(xiàn)方式:

        大多是基于數(shù)據(jù)版本(Version)記錄機(jī)制實(shí)現(xiàn),何謂數(shù)據(jù)版本?即為數(shù)據(jù)增加一個(gè)版本標(biāo)識(shí),在基于數(shù)據(jù)庫表的版本解決方案中,一般是通過為數(shù)據(jù)庫表增加一個(gè) “version” 字段來實(shí)現(xiàn)。

        讀取出數(shù)據(jù)時(shí),將此版本號(hào)一同讀出,之后更新時(shí),對(duì)此版本號(hào)加一。此時(shí),將提 交數(shù)據(jù)的版本數(shù)據(jù)與數(shù)據(jù)庫表對(duì)應(yīng)記錄的當(dāng)前版本信息進(jìn)行比對(duì),如果提交的數(shù)據(jù) 版本號(hào)大于數(shù)據(jù)庫表當(dāng)前版本號(hào),則予以更新,否則認(rèn)為是過期數(shù)據(jù)。
        假如系統(tǒng)中有一個(gè)Account的實(shí)體類,我們?cè)贏ccount中多加一個(gè)version字段,那么我們JDBC Sql語句將如下寫:
        e.g.

        Select a.version....from Account as a 
        where (where condition..)
        
        Update Account set version = version+1.....(another field) 
        where version =?...(another contidition)

        這樣以來我們就可以通過更新結(jié)果的行數(shù)來進(jìn)行判斷,如果更新結(jié)果的行數(shù)為0,那么說明實(shí)體從加載以來已經(jīng)被其它事務(wù)更改了,所以就拋出自定義的樂觀鎖定異常。具體實(shí)例如下:

        int rowsUpdated = statement.executeUpdate(sql);
        if (rowsUpdated ==0 ) {
         throws new OptimisticLockingFailureException();
        }

        悲觀鎖的實(shí)現(xiàn)

        Synchronized互斥鎖屬于悲觀鎖,它有一個(gè)明顯的缺點(diǎn),它不管數(shù)據(jù)存不存在競(jìng)爭(zhēng)都加鎖,隨著并發(fā)量增加,且如果鎖的時(shí)間比較長(zhǎng),其性能開銷將會(huì)變得很大。有沒有辦法解決這個(gè)問題?答案就是基于沖突檢測(cè)的樂觀鎖。這種模式下,已經(jīng)沒有所謂的鎖概念了,每條線程都直接先去執(zhí)行操作,計(jì)算完成后檢測(cè)是否與其他線程存在共享數(shù)據(jù)競(jìng)爭(zhēng),如果沒有則讓此操作成功,如果存在共享數(shù)據(jù)競(jìng)爭(zhēng)則可能不斷地重新執(zhí)行操作和檢測(cè),直到成功為止,這種叫做CAS自旋。

        Java里的CompareAndSet(CAS)

        以AtomicInteger的incrementAndGet的實(shí)現(xiàn)為例:

        incrementAndGet的實(shí)現(xiàn)
         public final int incrementAndGet() {
         for (;;) {
         int current = get();
         int next = current + 1;
         if (compareAndSet(current, next))
         return next;
         }
         }

        首先可以看到他是通過一個(gè)無限循環(huán)(spin)直到increment成功為止。

        循環(huán)的內(nèi)容是:

        1. 取得當(dāng)前值
        2. 計(jì)算+1后的值
        3. 如果當(dāng)前值還有效(沒有被)的話設(shè)置那個(gè)+1后的值
        4. 如果設(shè)置沒成功(當(dāng)前值已經(jīng)無效了即被別的線程改過了), 再從1開始。
        compareAndSet的實(shí)現(xiàn)
        public final boolean compareAndSet(int expect, int update) {
         return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
        }

        直接調(diào)用的是UnSafe這個(gè)類的compareAndSwapInt方法,全稱是sun.misc.Unsafe。這個(gè)類是Oracle(Sun)提供的實(shí)現(xiàn),可能在別的公司的JDK里就不是這個(gè)類了。

        compareAndSwapInt的實(shí)現(xiàn)
         /**
         * Atomically update Java variable to x if it is currently
         * holding expected.
         * @return true if successful
         */
         public final native boolean compareAndSwapInt(Object o, long offset, int expected, int x);
        
        

        此方法不是Java實(shí)現(xiàn)的,而是通過JNI調(diào)用操作系統(tǒng)的原生程序,涉及到CPU原子操作,現(xiàn)在幾乎所有的CPU指令都支持CAS的原子操作,X86下對(duì)應(yīng)的是CMPXCHG匯編指令。

        出于好奇,查看了下CAS原子操作的代碼描述:

        int compare_and_swap(int* reg, int oldval, int newval) {
         ATOMIC();
         int old_reg_val = *reg;
         if (old_reg_val == oldval)
         *reg = newval;
         END_ATOMIC();
         return old_reg_val;
        }

        也就是檢查內(nèi)存*reg里的值是不是oldval,如果是的話,則對(duì)其賦值newval。上面的代碼總是返回old_reg_value,調(diào)用者如果需要知道是否更新成功還需要做進(jìn)一步判斷,為了方便,它可以變種為直接返回是否更新成功,如下:

        bool compare_and_swap (int *accum, int *dest, int newval)
        {
         if ( *accum == *dest ) {
         *dest = newval;
         return true;
         }
         return false;
        }

        兩種鎖的比較

        兩種鎖各有優(yōu)缺點(diǎn),不可認(rèn)為一種好于另一種,像樂觀鎖適用于寫比較少的情況下,即沖突真的很少發(fā)生的時(shí)候,這樣可以省去了鎖的開銷,加大了系統(tǒng)的整個(gè)吞吐量。但如果經(jīng)常產(chǎn)生沖突,上層應(yīng)用會(huì)不斷的進(jìn)行retry,這樣反倒是降低了性能,所以這種情況下用悲觀鎖就比較合適。

        聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        悲觀鎖和樂觀鎖的比較和使用

        悲觀鎖和樂觀鎖的比較和使用:悲觀鎖(Pessimistic Lock) 顧名思義,就是 很悲觀 ,每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人會(huì)修改,所以每次在拿數(shù)據(jù)的時(shí)候都會(huì)上鎖,這樣別人想拿這個(gè)數(shù)據(jù)就會(huì)block直到它拿到鎖。傳統(tǒng)的關(guān)系型數(shù)據(jù)庫里邊就用到了很多這種鎖機(jī)制,比如行鎖,表鎖等,讀鎖,寫鎖等,
        推薦度:
        標(biāo)簽: 使用 區(qū)別 比較
        • 熱門焦點(diǎn)

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 亚洲AV无码乱码在线观看性色扶| 国产在线国偷精品产拍免费| 亚洲国产精品一区二区第一页免| 亚洲中文字幕一二三四区| 黄色网址免费观看| 亚洲人成在线免费观看| 亚洲一区在线免费观看| 亚洲成在人线电影天堂色| 最近2022中文字幕免费视频| 亚洲毛片免费观看| 好先生在线观看免费播放| 国产亚洲精品VA片在线播放| 全免费一级午夜毛片| 亚洲精品国产av成拍色拍| 免费一看一级毛片全播放| 九九免费观看全部免费视频| 日韩亚洲变态另类中文| 一区二区三区在线免费看| 亚洲天堂福利视频| 妞干网在线免费视频| 美女露隐私全部免费直播| 中文国产成人精品久久亚洲精品AⅤ无码精品 | 欧美日韩亚洲精品| 亚洲M码 欧洲S码SSS222| 国产一级a毛一级a看免费视频| 久久亚洲精品国产精品黑人| 狼群影院在线观看免费观看直播| 亚洲国产日韩在线成人蜜芽| 国产精品免费电影| 99在线视频免费观看| 亚洲性猛交xx乱| 亚洲国产成人久久精品99 | 亚洲国产精品无码久久久不卡| 中文字幕免费在线| 亚洲AV无码一区二区一二区| 亚洲熟妇无码八AV在线播放| xxxxwww免费| 一级女性全黄久久生活片免费| 亚洲av无码国产精品色午夜字幕| 最新中文字幕电影免费观看| 国产VA免费精品高清在线|