天天看點

Java 并發: ReentrantLock 的公平性

作者:不凡的牛仔很忙

ReentrantLock 是一個可重入的互斥鎖,它可以用于保護共享資源的通路。ReentrantLock 提供了公平鎖和非公平鎖兩種機制。

公平鎖會嚴格按照線程請求鎖的時間順序來配置設定鎖。而非公平鎖會忽略這種順序,随機選擇一個線程來配置設定鎖。

公平鎖的主要優點是避免線程饑餓,每個線程擷取鎖的等待時間比較平均。而非公平鎖能在整體上獲得更高的吞吐量,因為它減少了線程上下文切換的次數。

預設情況下,ReentrantLock 是非公平的。下面通過示例代碼來說明公平鎖和非公平鎖的差別:

非公平鎖:

ReentrantLock lock = new ReentrantLock();           

公平鎖:

ReentrantLock lock = new ReentrantLock(true);            

代碼示例:

public class FairnessTest {
    public static void main(String[] args) {
        ReentrantLock fairLock = new ReentrantLock(true);
        ReentrantLock unfairLock = new ReentrantLock();
        
        MyThread thread1 = new MyThread(fairLock, "Thread-1");
        MyThread thread2 = new MyThread(fairLock, "Thread-2");
        MyThread thread3 = new MyThread(unfairLock, "Thread-3");
        MyThread thread4 = new MyThread(unfairLock, "Thread-4");
        
        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();
    }
}

class MyThread extends Thread {
    private ReentrantLock lock;
    
    public MyThread(ReentrantLock lock, String name) {
        super(name);
        this.lock = lock;
    }
    
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            lock.lock();   // acquire the lock
            try {
                System.out.println(Thread.currentThread().getName() + 
                                   " is holding the lock...");
            } finally {
                lock.unlock();  // release the lock
            }
        } 
    }
}           

運作結果:

Thread-1 is holding the lock...

Thread-3 is holding the lock...

Thread-3 is holding the lock...

Thread-2 is holding the lock...

Thread-3 is holding the lock...

Thread-1 is holding the lock...

Thread-3 is holding the lock...

Thread-2 is holding the lock...

Thread-3 is holding the lock...

Thread-1 is holding the lock...

Thread-4 is holding the lock...

Thread-2 is holding the lock...

Thread-4 is holding the lock...

Thread-1 is holding the lock...

Thread-4 is holding the lock...

Thread-2 is holding the lock...

Thread-4 is holding the lock...

Thread-4 is holding the lock...

Thread-1 is holding the lock...

Thread-2 is holding the lock...

Process finished with exit code 0

我們可以看到,公平鎖(FairnessTest)按照線程請求的順序配置設定鎖,而非公平鎖(UnfairnessTest)随機選擇線程擷取鎖。是以,結論是:公平鎖可以避免線程饑餓,維持等待鎖的線程順序;而非公平鎖可以在整體上獲得更高的吞吐量。

繼續閱讀