Retrantlock使用

使用Retrantlock簡單示例:
class ReentrantLockUse extends Thread {

    public static ReentrantLock lock = new ReentrantLock();
    public static int i = 0;

    public ReentrantLockUse(String name) {
        super.setName(name);
    }

    @Override
    public void run() {
        for (int j = 0; j < 1000; j++) {
            lock.lock();
            try {
                System.out.println(this.getName() + " " + i);
                i++;
            } finally {
                lock.unlock();
            }
        }
    }
}

最後的結果會是 2000;如果去掉鎖,那麼輸出結果是一個小於2000的不確定的數,這個應該知道因爲可能多個線程同步執行某個步驟。

ReentrantLock與synchronized對比的優點:

1.可重入性
ReentrantLock和synchronized都是可重入的。synchronized因爲可重入因此可以放在被遞歸執行的方法上,且不用擔心線程最後能否正確釋放鎖;而ReentrantLock在重入時要卻確保重複獲取鎖的次數必須和重複釋放鎖的次數一樣,否則可能導致其他線程無法獲得該鎖。

2.鎖的實現方式
synchronized加鎖解鎖的過程是隱式的,用戶不用手動操作,系統去調度實現,優點是操作簡單,但顯得不夠靈活。一般併發場景使用synchronized的就夠了;ReentrantLock需要手動加鎖和解鎖,且解鎖的操作儘量要放在finally代碼塊中,保證線程正確釋放鎖。ReentrantLock操作較爲複雜,但是因爲可以手動控制加鎖和解鎖過程,在複雜的併發場景中能派上用場。

3.公平性
ReentrantLock提供了公平鎖和非公平鎖兩種API,開發人員完全可以根據應用場景選擇鎖的公平性;
synchronized是作爲Java關鍵字是依賴於JVM實現,Java團隊應該是優先考慮性能問題,因此synchronized是非公平鎖。

即相比於synchronized,ReentrantLock在功能上更加豐富,它具有可重入、可中斷、可限時、公平鎖等特點。

可重入性:
    public static void mian(String[] args) {
        ReentrantLock lock = new ReentrantLock();

        for (int i=0;i<3;i++) {
            lock.lock();
        }

        for (int i=0;i<3;i++) {
            lock.unlock();
        }
    }

上面的代碼通過lock()方法先獲取鎖三次,然後通過unlock()方法釋放鎖3次,程序可以正常退出。由於ReentrantLock是重入鎖,所以可以反覆得到相同的一把鎖,它有一個與鎖相關的獲取計數器state,如果擁有鎖的某個線程再次得到鎖,那麼獲取計數器就加1,然後鎖需要被釋放兩次才能獲得真正釋放(重入鎖)。

可中斷

與synchronized不同的是,ReentrantLock對中斷是有響應的.synchronized一旦嘗試獲取鎖就會一直等待直到獲取到鎖。使用ReentrantLock可通過中斷來避免死鎖。

可限時

超時不能獲得鎖,就返回false,不會永久等待構成死鎖
使用lock.tryLock(long timeout, TimeUnit unit)來實現可限時鎖,參數爲時間和單位。

可實現公平鎖

公平鎖: 是指多個線程競爭同一資源時[等待同一個鎖時],獲取資源的順序是按照申請鎖的先後順序的;公平鎖保障了多線程下各線程獲取鎖的順序,先到的線程優先獲取鎖,有點像早年買火車票一樣排隊早的人先買到火車票;
基本特點: 線程執行會嚴格按照順序執行,等待鎖的線程不會餓死,但 整體效率相對比較低;

非公平鎖: 是指多個線程競爭同一資源時,獲取資源的順序是不確定的,一般是搶佔式的;非公平鎖相對公平鎖是增加了獲取資源的不確定性,但是整體效率得以提升;
基本特點: 整體效率高,線程等待時間片具有不確定性;

ReentrantLock繼承於Lock類,在創建ReentrantLock的時候通過傳進參數true創建公平鎖,如果傳入的是false或沒傳參數則創建的是非公平鎖。

ReentrantLock lock = new ReentrantLock(true); //公平鎖
ReentrantLock lock = new ReentrantLock(); //非公平鎖

參考
Java中ReentrantLock的使用
ReentrantLock(重入鎖)功能詳解和應用演示

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章