91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

死磕 java同步系列之ReentrantLock VS synchronized——結果可能跟你想

發布時間:2020-07-24 11:40:08 來源:網絡 閱讀:261 作者:彤哥讀源碼 欄目:編程語言

問題

(1)ReentrantLock有哪些優點?

(2)ReentrantLock有哪些缺點?

(3)ReentrantLock是否可以完全替代synchronized?

簡介

synchronized是Java原生提供的用于在多線程環境中保證同步的關鍵字,底層是通過修改對象頭中的MarkWord來實現的。

ReentrantLock是Java語言層面提供的用于在多線程環境中保證同步的類,底層是通過原子更新狀態變量state來實現的。

既然有了synchronized的關鍵字來保證同步了,為什么還要實現一個ReentrantLock類呢?它們之間有什么異同呢?

ReentrantLock VS synchronized

直接上表格:(手機橫屏查看更方便)

功能 ReentrantLock synchronized
可重入 支持 支持
非公平 支持(默認) 支持
加鎖/解鎖方式 需要手動加鎖、解鎖,一般使用try..finally..保證鎖能夠釋放 手動加鎖,無需刻意解鎖
按key鎖 不支持,比如按用戶id加鎖 支持,synchronized加鎖時需要傳入一個對象
公平鎖 支持,new ReentrantLock(true) 不支持
中斷 支持,lockInterruptibly() 不支持
嘗試加鎖 支持,tryLock() 不支持
超時鎖 支持,tryLock(timeout, unit) 不支持
獲取當前線程獲取鎖的次數 支持,getHoldCount() 不支持
獲取等待的線程 支持,getWaitingThreads() 不支持
檢測是否被當前線程占有 支持,isHeldByCurrentThread() 不支持
檢測是否被任意線程占有 支持,isLocked() 不支持
條件鎖 可支持多個條件,condition.await(),condition.signal(),condition.signalAll() 只支持一個,obj.wait(),obj.notify(),obj.notifyAll()

對比測試

在測試之前,我們先預想一下結果,隨著線程數的不斷增加,ReentrantLock(fair)、ReentrantLock(unfair)、synchronized三者的效率怎樣呢?

我猜測應該是ReentrantLock(unfair)> synchronized > ReentrantLock(fair)。

到底是不是這樣呢?

直接上測試代碼:(為了全面對比,彤哥這里把AtomicInteger和LongAdder也拿來一起對比了)

public class ReentrantLockVsSynchronizedTest {
    public static AtomicInteger a = new AtomicInteger(0);
    public static LongAdder b = new LongAdder();
    public static int c = 0;
    public static int d = 0;
    public static int e = 0;

    public static final ReentrantLock fairLock = new ReentrantLock(true);
    public static final ReentrantLock unfairLock = new ReentrantLock();

    public static void main(String[] args) throws InterruptedException {
        System.out.println("-------------------------------------");
        testAll(1, 100000);
        System.out.println("-------------------------------------");
        testAll(2, 100000);
        System.out.println("-------------------------------------");
        testAll(4, 100000);
        System.out.println("-------------------------------------");
        testAll(6, 100000);
        System.out.println("-------------------------------------");
        testAll(8, 100000);
        System.out.println("-------------------------------------");
        testAll(10, 100000);
        System.out.println("-------------------------------------");
        testAll(50, 100000);
        System.out.println("-------------------------------------");
        testAll(100, 100000);
        System.out.println("-------------------------------------");
        testAll(200, 100000);
        System.out.println("-------------------------------------");
        testAll(500, 100000);
        System.out.println("-------------------------------------");
//        testAll(1000, 1000000);
        System.out.println("-------------------------------------");
        testAll(500, 10000);
        System.out.println("-------------------------------------");
        testAll(500, 1000);
        System.out.println("-------------------------------------");
        testAll(500, 100);
        System.out.println("-------------------------------------");
        testAll(500, 10);
        System.out.println("-------------------------------------");
        testAll(500, 1);
        System.out.println("-------------------------------------");
    }

    public static void testAll(int threadCount, int loopCount) throws InterruptedException {
        testAtomicInteger(threadCount, loopCount);
        testLongAdder(threadCount, loopCount);
        testSynchronized(threadCount, loopCount);
        testReentrantLockUnfair(threadCount, loopCount);
//        testReentrantLockFair(threadCount, loopCount);
    }

    public static void testAtomicInteger(int threadCount, int loopCount) throws InterruptedException {
        long start = System.currentTimeMillis();

        CountDownLatch countDownLatch = new CountDownLatch(threadCount);
        for (int i = 0; i < threadCount; i++) {
            new Thread(() -> {
                for (int j = 0; j < loopCount; j++) {
                    a.incrementAndGet();
                }
                countDownLatch.countDown();
            }).start();
        }

        countDownLatch.await();

        System.out.println("testAtomicInteger: result=" + a.get() + ", threadCount=" + threadCount + ", loopCount=" + loopCount + ", elapse=" + (System.currentTimeMillis() - start));
    }

    public static void testLongAdder(int threadCount, int loopCount) throws InterruptedException {
        long start = System.currentTimeMillis();

        CountDownLatch countDownLatch = new CountDownLatch(threadCount);
        for (int i = 0; i < threadCount; i++) {
            new Thread(() -> {
                for (int j = 0; j < loopCount; j++) {
                    b.increment();
                }
                countDownLatch.countDown();
            }).start();
        }

        countDownLatch.await();

        System.out.println("testLongAdder: result=" + b.sum() + ", threadCount=" + threadCount + ", loopCount=" + loopCount + ", elapse=" + (System.currentTimeMillis() - start));
    }

    public static void testReentrantLockFair(int threadCount, int loopCount) throws InterruptedException {
        long start = System.currentTimeMillis();

        CountDownLatch countDownLatch = new CountDownLatch(threadCount);
        for (int i = 0; i < threadCount; i++) {
            new Thread(() -> {
                for (int j = 0; j < loopCount; j++) {
                    fairLock.lock();
                    // 消除try的性能影響
//                    try {
                        c++;
//                    } finally {
                        fairLock.unlock();
//                    }
                }
                countDownLatch.countDown();
            }).start();
        }

        countDownLatch.await();

        System.out.println("testReentrantLockFair: result=" + c + ", threadCount=" + threadCount + ", loopCount=" + loopCount + ", elapse=" + (System.currentTimeMillis() - start));
    }

    public static void testReentrantLockUnfair(int threadCount, int loopCount) throws InterruptedException {
        long start = System.currentTimeMillis();

        CountDownLatch countDownLatch = new CountDownLatch(threadCount);
        for (int i = 0; i < threadCount; i++) {
            new Thread(() -> {
                for (int j = 0; j < loopCount; j++) {
                    unfairLock.lock();
                    // 消除try的性能影響
//                    try {
                        d++;
//                    } finally {
                        unfairLock.unlock();
//                    }
                }
                countDownLatch.countDown();
            }).start();
        }

        countDownLatch.await();

        System.out.println("testReentrantLockUnfair: result=" + d + ", threadCount=" + threadCount + ", loopCount=" + loopCount + ", elapse=" + (System.currentTimeMillis() - start));
    }

    public static void testSynchronized(int threadCount, int loopCount) throws InterruptedException {
        long start = System.currentTimeMillis();

        CountDownLatch countDownLatch = new CountDownLatch(threadCount);
        for (int i = 0; i < threadCount; i++) {
            new Thread(() -> {
                for (int j = 0; j < loopCount; j++) {
                    synchronized (ReentrantLockVsSynchronizedTest.class) {
                        e++;
                    }
                }
                countDownLatch.countDown();
            }).start();
        }

        countDownLatch.await();

        System.out.println("testSynchronized: result=" + e + ", threadCount=" + threadCount + ", loopCount=" + loopCount + ", elapse=" + (System.currentTimeMillis() - start));
    }

}

運行這段代碼,你會發現結果大大出乎意料,真的是不測不知道,一測嚇一跳,運行后發現以下規律:

隨著線程數的不斷增加,synchronized的效率竟然比ReentrantLock非公平模式要高!

彤哥的電腦上大概是高3倍左右,我的運行環境是4核8G,java版本是8,請大家一定要在自己電腦上運行一下,并且最好能給我反饋一下。

彤哥又使用Java7及以下的版本運行了,發現在Java7及以下版本中synchronized的效率確實比ReentrantLock的效率低一些。

總結

(1)synchronized是Java原生關鍵字鎖;

(2)ReentrantLock是Java語言層面提供的鎖;

(3)ReentrantLock的功能非常豐富,解決了很多synchronized的局限性;

(4)至于在非公平模式下,ReentrantLock與synchronized的效率孰高孰低,彤哥給出的結論是隨著Java版本的不斷升級,synchronized的效率只會越來越高;

彩蛋

既然ReentrantLock的功能更豐富,而且效率也不低,我們是不是可以放棄使用synchronized了呢?

答:我認為不是。因為synchronized是Java原生支持的,隨著Java版本的不斷升級,Java團隊也是在不斷優化synchronized,所以我認為在功能相同的前提下,最好還是使用原生的synchronized關鍵字來加鎖,這樣我們就能獲得Java版本升級帶來的免費的性能提升的空間。

另外,在Java8的ConcurrentHashMap中已經把ReentrantLock換成了synchronized來分段加鎖了,這也是Java版本不斷升級帶來的免費的synchronized的性能提升。

推薦閱讀

  1. 死磕 java同步系列之ReentrantLock源碼解析(二)——條件鎖

  2. 死磕 java同步系列之ReentrantLock源碼解析(一)——公平鎖、非公平鎖

  3. 死磕 java同步系列之AQS起篇

  4. 死磕 java同步系列之自己動手寫一個鎖Lock

  5. 死磕 java魔法類之Unsafe解析

  6. 死磕 java同步系列之JMM(Java Memory Model)

  7. 死磕 java同步系列之volatile解析

  8. 死磕 java同步系列之synchronized解析

歡迎關注我的公眾號“彤哥讀源碼”,查看更多源碼系列文章, 與彤哥一起暢游源碼的海洋。

死磕 java同步系列之ReentrantLock VS synchronized——結果可能跟你想

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

勃利县| 柞水县| 榆树市| 林西县| 齐齐哈尔市| 拜城县| 含山县| 桑日县| 固安县| 鞍山市| 柘城县| 册亨县| 景东| 隆尧县| 南康市| 武宣县| 芦山县| 略阳县| 习水县| 巴东县| 雷州市| 安阳县| 安图县| 黄浦区| 石泉县| 高安市| 新营市| 邹平县| 孝义市| 琼结县| 同仁县| 英山县| 怀远县| 安多县| 余姚市| 汉川市| 长汀县| 灵宝市| 竹溪县| 行唐县| 双城市|