一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

自旋鎖、排隊(duì)自旋鎖、MCS鎖、CLH鎖(轉(zhuǎn))

 hh3755 2014-08-11

自旋鎖(Spin lock)

轉(zhuǎn):http:///index.php/concurrent/20131115/577

自旋鎖是指當(dāng)一個(gè)線程嘗試獲取某個(gè)鎖時(shí),如果該鎖已被其他線程占用,就一直循環(huán)檢測(cè)鎖是否被釋放,而不是進(jìn)入線程掛起或睡眠狀態(tài)。

自旋鎖適用于鎖保護(hù)的臨界區(qū)很小的情況,臨界區(qū)很小的話,鎖占用的時(shí)間就很短。

簡(jiǎn)單的實(shí)現(xiàn)

import java.util.concurrent.atomic.AtomicReference;

public class SpinLock {
   private AtomicReference<Thread> owner = new AtomicReference<Thread>();

   public void lock() {
       Thread currentThread = Thread.currentThread();

              // 如果鎖未被占用,則設(shè)置當(dāng)前線程為鎖的擁有者
       while (owner.compareAndSet(null, currentThread)) {
       }
   }

   public void unlock() {
       Thread currentThread = Thread.currentThread();

              // 只有鎖的擁有者才能釋放鎖
       owner.compareAndSet(currentThread, null);
   }
}

SimpleSpinLock里有一個(gè)owner屬性持有鎖當(dāng)前擁有者的線程的引用,如果該引用為null,則表示鎖未被占用,不為null則被占用。

這里用AtomicReference是為了使用它的原子性的compareAndSet方法(CAS操作),解決了多線程并發(fā)操作導(dǎo)致數(shù)據(jù)不一致的問(wèn)題,確保其他線程可以看到鎖的真實(shí)狀態(tài)。

缺點(diǎn)

  1. CAS操作需要硬件的配合;
  2. 保證各個(gè)CPU的緩存(L1、L2、L3、跨CPU Socket、主存)的數(shù)據(jù)一致性,通訊開(kāi)銷(xiāo)很大,在多處理器系統(tǒng)上更嚴(yán)重;
  3. 沒(méi)法保證公平性,不保證等待進(jìn)程/線程按照FIFO順序獲得鎖。

Ticket Lock

Ticket Lock 是為了解決上面的公平性問(wèn)題,類(lèi)似于現(xiàn)實(shí)中銀行柜臺(tái)的排隊(duì)叫號(hào):鎖擁有一個(gè)服務(wù)號(hào),表示正在服務(wù)的線程,還有一個(gè)排隊(duì)號(hào);每個(gè)線程嘗試獲取鎖之前先拿一個(gè)排隊(duì)號(hào),然后不斷輪詢鎖的當(dāng)前服務(wù)號(hào)是否是自己的排隊(duì)號(hào),如果是,則表示自己擁有了鎖,不是則繼續(xù)輪詢。

當(dāng)線程釋放鎖時(shí),將服務(wù)號(hào)加1,這樣下一個(gè)線程看到這個(gè)變化,就退出自旋。

簡(jiǎn)單的實(shí)現(xiàn)

import java.util.concurrent.atomic.AtomicInteger;

public class TicketLock {
   private AtomicInteger serviceNum = new AtomicInteger(); // 服務(wù)號(hào)
   private AtomicInteger ticketNum = new AtomicInteger(); // 排隊(duì)號(hào)

   public int lock() {
         // 首先原子性地獲得一個(gè)排隊(duì)號(hào)
         int myTicketNum = ticketNum.getAndIncrement();

              // 只要當(dāng)前服務(wù)號(hào)不是自己的就不斷輪詢
       while (serviceNum.get() != myTicketNum) {
       }

       return myTicketNum;
    }

    public void unlock(int myTicket) {
        // 只有當(dāng)前線程擁有者才能釋放鎖
        int next = myTicket + 1;
        serviceNum.compareAndSet(myTicket, next);
    }
}

缺點(diǎn)

Ticket Lock 雖然解決了公平性的問(wèn)題,但是多處理器系統(tǒng)上,每個(gè)進(jìn)程/線程占用的處理器都在讀寫(xiě)同一個(gè)變量serviceNum ,每次讀寫(xiě)操作都必須在多個(gè)處理器緩存之間進(jìn)行緩存同步,這會(huì)導(dǎo)致繁重的系統(tǒng)總線和內(nèi)存的流量,大大降低系統(tǒng)整體的性能。

下面介紹的CLH鎖和MCS鎖都是為了解決這個(gè)問(wèn)題的。

MCS 來(lái)自于其發(fā)明人名字的首字母: John Mellor-Crummey和Michael Scott。

CLH的發(fā)明人是:Craig,Landin and Hagersten。

MCS鎖

MCS Spinlock 是一種基于鏈表的可擴(kuò)展、高性能、公平的自旋鎖,申請(qǐng)線程只在本地變量上自旋,直接前驅(qū)負(fù)責(zé)通知其結(jié)束自旋,從而極大地減少了不必要的處理器緩存同步的次數(shù),降低了總線和內(nèi)存的開(kāi)銷(xiāo)。

import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

public class MCSLock {
    public static class MCSNode {
        MCSNode next;
        boolean isLocked = true; // 默認(rèn)是在等待鎖
    }

    volatile MCSNode queue ;// 指向最后一個(gè)申請(qǐng)鎖的MCSNode
    private static final AtomicReferenceFieldUpdater<MCSLock, MCSNode> UPDATER = AtomicReferenceFieldUpdater
                  . newUpdater(MCSLock.class, MCSNode. class, "queue" );

    public void lock(MCSNode currentThread) {
        MCSNode predecessor = UPDATER.getAndSet(this, currentThread);// step 1
        if (predecessor != null) {
            predecessor.next = currentThread;// step 2

            while (currentThread.isLocked ) {// step 3
            }
        }
    }

    public void unlock(MCSNode currentThread) {
        if ( UPDATER.get( this ) == currentThread) {// 鎖擁有者進(jìn)行釋放鎖才有意義
            if (currentThread.next == null) {// 檢查是否有人排在自己后面
                if (UPDATER.compareAndSet(this, currentThread, null)) {// step 4
                    // compareAndSet返回true表示確實(shí)沒(méi)有人排在自己后面
                    return;
                } else {
                    // 突然有人排在自己后面了,可能還不知道是誰(shuí),下面是等待后續(xù)者
                    // 這里之所以要忙等是因?yàn)椋簊tep 1執(zhí)行完后,step 2可能還沒(méi)執(zhí)行完
                    while (currentThread.next == null) { // step 5
                    }
                }
            }

            currentThread.next.isLocked = false;
            currentThread.next = null;// for GC
        }
    }
}

CLH鎖

CLH鎖也是一種基于鏈表的可擴(kuò)展、高性能、公平的自旋鎖,申請(qǐng)線程只在本地變量上自旋,它不斷輪詢前驅(qū)的狀態(tài),如果發(fā)現(xiàn)前驅(qū)釋放了鎖就結(jié)束自旋。

import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

public class CLHLock {
    public static class CLHNode {
        private boolean isLocked = true; // 默認(rèn)是在等待鎖
    }

    @SuppressWarnings("unused" )
    private volatile CLHNode tail ;
    private static final AtomicReferenceFieldUpdater<CLHLock, CLHNode> UPDATER = AtomicReferenceFieldUpdater
                  . newUpdater(CLHLock.class, CLHNode .class , "tail" );

    public void lock(CLHNode currentThread) {
        CLHNode preNode = UPDATER.getAndSet( this, currentThread);
        if(preNode != null) {//已有線程占用了鎖,進(jìn)入自旋
            while(preNode.isLocked ) {
            }
        }
    }

    public void unlock(CLHNode currentThread) {
        // 如果隊(duì)列里只有當(dāng)前線程,則釋放對(duì)當(dāng)前線程的引用(for GC)。
        if (!UPDATER .compareAndSet(this, currentThread, null)) {
            // 還有后續(xù)線程
            currentThread. isLocked = false ;// 改變狀態(tài),讓后續(xù)線程結(jié)束自旋
        }
    }
}

CLH鎖 與 MCS鎖 的比較

下圖是CLH鎖和MCS鎖隊(duì)列圖示:
CLH-MCS-SpinLock

差異:

  1. 從代碼實(shí)現(xiàn)來(lái)看,CLH比MCS要簡(jiǎn)單得多。
  2. 從自旋的條件來(lái)看,CLH是在本地變量上自旋,MCS是自旋在其他對(duì)象的屬性。
  3. 從鏈表隊(duì)列來(lái)看,CLH的隊(duì)列是隱式的,CLHNode并不實(shí)際持有下一個(gè)節(jié)點(diǎn);MCS的隊(duì)列是物理存在的。
  4. CLH鎖釋放時(shí)只需要改變自己的屬性,MCS鎖釋放則需要改變后繼節(jié)點(diǎn)的屬性。

注意:這里實(shí)現(xiàn)的鎖都是獨(dú)占的,且不能重入的。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多

    中文字幕日韩无套内射| 91亚洲熟女少妇在线观看| 深夜福利欲求不满的人妻| 在线观看那种视频你懂的| 欧美又黑又粗大又硬又爽| 欧美日韩精品视频在线| 欧美日本精品视频在线观看| 黄色片国产一区二区三区| 免费亚洲黄色在线观看| 中国少妇精品偷拍视频 | 亚洲一区二区三区在线免费| 久草国产精品一区二区| 亚洲精品国产美女久久久99| 中国美女草逼一级黄片视频| 日本欧美视频在线观看免费| 青青操视频在线播放免费| 久久精品色妇熟妇丰满人妻91| 日本免费一本一二区三区| 中文字幕一区二区熟女| 欧洲亚洲精品自拍偷拍| 国产一二三区不卡视频| 国产又大又硬又粗又湿| 午夜精品成年人免费视频| 国产又粗又爽又猛又黄的| 激情三级在线观看视频| 国产麻豆一区二区三区在| 欧美日韩亚洲综合国产人| 欧美日韩少妇精品专区性色| 日韩黄片大全免费在线看| 亚洲欧洲日韩综合二区| 免费特黄一级一区二区三区| 亚洲综合天堂一二三区| 香港国产三级久久精品三级| 国产午夜福利片在线观看| 日韩不卡一区二区三区色图| 日韩性生活视频免费在线观看| 欧美日韩亚洲国产综合网| 亚洲中文字幕熟女丝袜久久 | 在线观看视频国产你懂的| 综合久综合久综合久久| 亚洲精品一区三区三区|