synchronized與ReentrantLock的區別

Real_man發表於2019-05-04

這是一個老生常談的問題,但是如果僅僅是那些比較普遍的說法,我也不用記錄這篇文章,今天在寫兩者程式碼的時候還有一個不容易發現到的區別點。

常規區別

  • ReentrantLock更加靈活,提供了超時獲取鎖,可中斷鎖。提供了非公平鎖和非公平鎖,而synchronized僅僅是非公平鎖。
  • 用法上,ReentrantLock必須手動釋放鎖,並且只能修飾程式碼塊。而synchronized不用手動釋放鎖,除此之外可以修飾方法。

還有一個區別是使用synchronized的執行緒會被block住,而ReentrantLock的執行緒則是進入waiting狀態

疑問點

ReentrantLock真的比synchronized效能高嗎?

我寫了一個簡單的demo

public class LockDemo {

    static ReentrantLock lock = new ReentrantLock(false);

    public static void main(String[] args) {
        syncTest();
		 //分別測試
//        lockTest();
    }


    public static void syncTest() {
        for (int i = 0; i < 10; i++) {
            new Thread() {
                @Override
                public void run() {
                    synchronized (lock) {
                        System.out.println(Thread.currentThread().getName() + "開始鎖定");
                        try {
                            Thread.sleep(2 * 1000);
                        } catch (Exception e) {
                            e.printStackTrace();
                        } finally {
                            System.out.println(Thread.currentThread().getName() + "解鎖");

                        }
                    }
                }
            }.start();
        }
    }

    public static void lockTest() {
        for (int i = 0; i < 10; i++) {
            new Thread() {
                @Override
                public void run() {
                    lock.lock();
                    System.out.println(Thread.currentThread().getName() + "開始鎖定");
                    try {
                        Thread.sleep(2 * 1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        System.out.println(Thread.currentThread().getName() + "解鎖");
                        lock.unlock();
                    }
                }
            }.start();
        }
    }

}

複製程式碼

執行的結果如下:

Synchonized,其執行緒狀態只有time_waiting與blocked,當獲取到鎖的執行緒執行完畢之後,其餘執行緒會一起再次爭搶鎖

image-20190504181956547

image-20190504182035887

ReentrantLock的非公平鎖測試,儘管我用的是非公平鎖,但是看起來還是有公平性的。其內部執行緒進入的是waiting狀態

image-20190504182246124

image-20190504182334411

至於是否效能是高點,我覺得單個執行緒去獲取鎖會比多個執行緒一起去搶鎖效能會高一些吧,synchronized對鎖做的優化也只是在單執行緒以及兩個執行緒的時候做的優化,一旦升級為重量級鎖,那些優化也就沒有效果了。

當然這是個人猜測。

最後

這裡其實看ReentrantLock內部的原始碼可以看到細節。

  • Locksupport.park,執行緒會進入waiting狀態
  • ReentrantLock儘管使用的是非公平鎖,但是如果有新的執行緒嘗試獲取到鎖的時候,只有當前的執行緒會去爭搶鎖。

相關文章