成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

AQS同步組件--ReentrantLock與鎖

dcr309duan / 2568人閱讀

摘要:性能較好是因?yàn)楸苊饬司€程進(jìn)入內(nèi)核的阻塞狀態(tài)請(qǐng)求總數(shù)同時(shí)并發(fā)執(zhí)行的線程數(shù)我們首先使用聲明一個(gè)所得實(shí)例,然后使用進(jìn)行加鎖和解鎖操作。

ReentrantLock與鎖
Synchronized和ReentrantLock異同

可重入性:兩者都具有可重入性

鎖的實(shí)現(xiàn):Synchronized是依賴jvm實(shí)現(xiàn)的,ReentrantLock是jdk實(shí)現(xiàn)的。(我們可以理解為一個(gè)是操作系統(tǒng)層面的實(shí)現(xiàn)另一個(gè)是用戶自己自己實(shí)現(xiàn)的)Synchronized的實(shí)現(xiàn)是jvm層面的很難看到其中的實(shí)現(xiàn)。而ReentrantLock是通過jvm實(shí)現(xiàn)的我們可以通過閱讀jvm源碼來查看實(shí)現(xiàn)。

性能區(qū)別:在Synchronized優(yōu)化之前Synchronized的性能相比ReentrantLock差很多,在Synchronized引入了偏向鎖,輕量級(jí)鎖也就是自旋鎖之后了,兩者的性能相差不大了。在兩者都可用的情況下官方更推薦使用Synchronized,因?yàn)槠鋵懛ǜ唵?,Synchronized的優(yōu)化就是借鑒了ReentrantLock中的cas技術(shù)。

功能區(qū)別:便利性,很明顯synchronized的使用更加便利,ReentrantLock在細(xì)粒度和靈活性中會(huì)優(yōu)于Synchronized。

ReentrantLock獨(dú)有功能

ReentrantLock可指定是公平鎖還是非公平鎖,Synchronized只能是非公平鎖。(公平鎖就是先等待的線程先獲得鎖)

ReentrantLock提供一個(gè)Condition類,可以分組喚醒需要喚醒的形成。synchronized是要嘛隨機(jī)喚醒一個(gè)線程要嘛喚醒所有的線程。

ReentrantLock提供了一種能夠中斷等待鎖的線程的機(jī)制lock.locInterruptibly(),ReentrantLock實(shí)現(xiàn)是一種自旋鎖通過循環(huán)調(diào)用,通過cas機(jī)制來實(shí)現(xiàn)加鎖。性能較好是因?yàn)楸苊饬司€程進(jìn)入內(nèi)核的阻塞狀態(tài)

@Slf4j
public class LockExample2 {

    // 請(qǐng)求總數(shù)
    public static int clientTotal = 5000;

    // 同時(shí)并發(fā)執(zhí)行的線程數(shù)
    public static int threadTotal = 200;

    public static int count = 0;

    private final static Lock lock = new ReentrantLock();

    public static void main(String[] args) throws Exception {
        ExecutorService executorService = Executors.newCachedThreadPool();
        final Semaphore semaphore = new Semaphore(threadTotal);
        final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
        for (int i = 0; i < clientTotal ; i++) {
            executorService.execute(() -> {
                try {
                    semaphore.acquire();
                    add();
                    semaphore.release();
                } catch (Exception e) {
                    log.error("exception", e);
                }
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        executorService.shutdown();
        log.info("count:{}", count);
    }

    private static void add() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }
}

我們首先使用 private final static Lock lock = new ReentrantLock()聲明一個(gè)所得實(shí)例,然后使用

lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }

進(jìn)行加鎖和解鎖操作。

我們?cè)谕ㄟ^一個(gè)例子來看看這個(gè)ReentrantReadWriteLock怎么用。

@Slf4j
public class LockExample3 {

    private final Map map = new TreeMap<>();

    private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    private final Lock readLock = lock.readLock();

    private final Lock writeLock = lock.writeLock();

    public Data get(String key) {
        readLock.lock();
        try {
            return map.get(key);
        } finally {
            readLock.unlock();
        }
    }

    public Set getAllKeys() {
        readLock.lock();
        try {
            return map.keySet();
        } finally {
            readLock.unlock();
        }
    }

    public Data put(String key, Data value) {
        writeLock.lock();
        try {
            return map.put(key, value);
        } finally {
            readLock.unlock();
        }
    }

    class Data {

    }
}

通過 private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock()聲明一個(gè)ReentrantReadWriteLock,然后再分別獲取 private final Lock readLock = lock.readLock() private final Lock writeLock = lock.writeLock()讀鎖和寫鎖。
我們?cè)谶@個(gè)map讀的時(shí)候加上讀鎖在寫的時(shí)候加上寫鎖,但是這里有問題就是這個(gè)鎖是悲觀鎖,也就是說在執(zhí)行寫鎖的時(shí)候一定不能有讀鎖,當(dāng)讀操作特 特別多的時(shí)候很有可能會(huì)讓寫鎖一直無法執(zhí)行。

我們看一下官方的例子學(xué)習(xí)一下,StampedLock

import java.util.concurrent.locks.StampedLock;

public class LockExample4 {

    class Point {
        private double x, y;
        private final StampedLock sl = new StampedLock();

        void move(double deltaX, double deltaY) { // an exclusively locked method
            long stamp = sl.writeLock();
            try {
                x += deltaX;
                y += deltaY;
            } finally {
                sl.unlockWrite(stamp);
            }
        }

        //下面看看樂觀讀鎖案例
        double distanceFromOrigin() { // A read-only method
            long stamp = sl.tryOptimisticRead(); //獲得一個(gè)樂觀讀鎖
            double currentX = x, currentY = y;  //將兩個(gè)字段讀入本地局部變量
            if (!sl.validate(stamp)) { //檢查發(fā)出樂觀讀鎖后同時(shí)是否有其他寫鎖發(fā)生?
                stamp = sl.readLock();  //如果沒有,我們?cè)俅潍@得一個(gè)讀悲觀鎖
                try {
                    currentX = x; // 將兩個(gè)字段讀入本地局部變量
                    currentY = y; // 將兩個(gè)字段讀入本地局部變量
                } finally {
                    sl.unlockRead(stamp);
                }
            }
            return Math.sqrt(currentX * currentX + currentY * currentY);
        }

        //下面是悲觀讀鎖案例
        void moveIfAtOrigin(double newX, double newY) { // upgrade
            // Could instead start with optimistic, not read mode
            long stamp = sl.readLock();
            try {
                while (x == 0.0 && y == 0.0) { //循環(huán),檢查當(dāng)前狀態(tài)是否符合
                    long ws = sl.tryConvertToWriteLock(stamp); //將讀鎖轉(zhuǎn)為寫鎖
                    if (ws != 0L) { //這是確認(rèn)轉(zhuǎn)為寫鎖是否成功
                        stamp = ws; //如果成功 替換票據(jù)
                        x = newX; //進(jìn)行狀態(tài)改變
                        y = newY;  //進(jìn)行狀態(tài)改變
                        break;
                    } else { //如果不能成功轉(zhuǎn)換為寫鎖
                        sl.unlockRead(stamp);  //我們顯式釋放讀鎖
                        stamp = sl.writeLock();  //顯式直接進(jìn)行寫鎖 然后再通過循環(huán)再試
                    }
                }
            } finally {
                sl.unlock(stamp); //釋放讀鎖或?qū)戞i
            }
        }
    }
}

我們?cè)賹⑶懊娴睦锔某蒘tampedLock

@Slf4j
public class LockExample5 {

    // 請(qǐng)求總數(shù)
    public static int clientTotal = 5000;

    // 同時(shí)并發(fā)執(zhí)行的線程數(shù)
    public static int threadTotal = 200;

    public static int count = 0;

    private final static StampedLock lock = new StampedLock();

    public static void main(String[] args) throws Exception {
        ExecutorService executorService = Executors.newCachedThreadPool();
        final Semaphore semaphore = new Semaphore(threadTotal);
        final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
        for (int i = 0; i < clientTotal ; i++) {
            executorService.execute(() -> {
                try {
                    semaphore.acquire();
                    add();
                    semaphore.release();
                } catch (Exception e) {
                    log.error("exception", e);
                }
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        executorService.shutdown();
        log.info("count:{}", count);
    }

    private static void add() {
        long stamp = lock.writeLock();
        try {
            count++;
        } finally {
            lock.unlock(stamp);
        }
    }
}

這里和之前的不一樣的地方就是

   long stamp = lock.writeLock();
        try {
            count++;
        } finally {
            lock.unlock(stamp);
        }

在加鎖后會(huì)返回一個(gè)值,解鎖的時(shí)候需要傳入這個(gè)值。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/77684.html

相關(guān)文章

  • Java中的鎖

    摘要:當(dāng)前線程在超時(shí)時(shí)間內(nèi)被中斷超時(shí)時(shí)間結(jié)束,返回釋放鎖獲取等待通知組件,該組件和當(dāng)前的鎖綁定,當(dāng)前線程只有獲取了鎖,才能調(diào)用該組件的方法,調(diào)用后,當(dāng)前線程將釋放鎖。同步器是實(shí)現(xiàn)鎖的關(guān)鍵,在鎖的實(shí)現(xiàn)中聚合同步器,利用同步器實(shí)現(xiàn)鎖的語義。 本文在參考java并發(fā)編程實(shí)戰(zhàn)后完成,參考內(nèi)容較多 Java中的鎖 鎖是用來控制多線程訪問共享資源的方式,一個(gè)鎖能夠防止多個(gè)線程同事訪問共享資源。在Lock...

    gaara 評(píng)論0 收藏0
  • 【java并發(fā)編程實(shí)戰(zhàn)6】AQS之獨(dú)占鎖ReentrantLock實(shí)現(xiàn)

    摘要:鎖與很好的隔離使用者與實(shí)現(xiàn)者所需要關(guān)注的領(lǐng)域。那么這個(gè)就是包裝線程并且放入到隊(duì)列的過程實(shí)現(xiàn)的方法。也證實(shí)了就是獲取鎖的線程的節(jié)點(diǎn)。如果發(fā)生異常取消請(qǐng)求,也就是將當(dāng)前節(jié)點(diǎn)重隊(duì)列中移除。 前言 自從JDK1.5后,jdk新增一個(gè)并發(fā)工具包java.util.concurrent,提供了一系列的并發(fā)工具類。而今天我們需要學(xué)習(xí)的是java.util.concurrent.lock也就是它下面的...

    sixleaves 評(píng)論0 收藏0
  • J.U.C|一文搞懂AQS

    摘要:接著線程過來通過方式獲取鎖,獲取鎖的過程就是通過操作變量將其值從變?yōu)?。線程加鎖成功后還有一步重要的操作,就是將設(shè)置成為自己。線程屁顛屁顛的就去等待區(qū)小憩一會(huì)去了。 一、寫在前面 這篇文章,我們聊一聊Java并發(fā)中的核武器, AQS底層實(shí)現(xiàn)。 不管是工作三四年、還是五六年的在工作或者面試中涉及到并發(fā)的是時(shí)候總是繞不過AQS這個(gè)詞。 首先,確實(shí)還有很多人連AQS是什么都不知道,甚至有的竟...

    tommego 評(píng)論0 收藏0
  • Java 線程同步組件 CountDownLatch 與 CyclicBarrier 原理分析

    摘要:在創(chuàng)建對(duì)象時(shí),需要轉(zhuǎn)入一個(gè)值,用于初始化的成員變量,該成員變量表示屏障攔截的線程數(shù)。當(dāng)?shù)竭_(dá)屏障的線程數(shù)小于時(shí),這些線程都會(huì)被阻塞住。當(dāng)所有線程到達(dá)屏障后,將會(huì)被更新,表示進(jìn)入新一輪的運(yùn)行輪次中。 1.簡介 在分析完AbstractQueuedSynchronizer(以下簡稱 AQS)和ReentrantLock的原理后,本文將分析 java.util.concurrent 包下的兩個(gè)...

    Anonymous1 評(píng)論0 收藏0
  • Java 重入鎖 ReentrantLock 原理分析

    摘要:的主要功能和關(guān)鍵字一致,均是用于多線程的同步。而僅支持通過查詢當(dāng)前線程是否持有鎖。由于和使用的是同一把可重入鎖,所以線程可以進(jìn)入方法,并再次獲得鎖,而不會(huì)被阻塞住。公平與非公平公平與非公平指的是線程獲取鎖的方式。 1.簡介 可重入鎖ReentrantLock自 JDK 1.5 被引入,功能上與synchronized關(guān)鍵字類似。所謂的可重入是指,線程可對(duì)同一把鎖進(jìn)行重復(fù)加鎖,而不會(huì)被阻...

    lx1036 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<