Java中的公平鎖和非公平鎖
公平鎖
特點
-
排隊機制:
-
線程請求鎖時,如果鎖被占用,會進入一個等待隊列。
-
當鎖被釋放時,隊列中等待最久的線程優先獲得鎖。
-
-
避免線程饑餓:
-
公平鎖可以防止某些線程長時間無法獲取鎖的問題。
-
-
性能較低:
-
排隊和喚醒線程的開銷較高,可能導致整體性能下降。
-
實現方式
在 Java 的 ReentrantLock 中,通過將構造方法的參數 fair 設置為 true 來啟用公平鎖:
ReentrantLock lock = new ReentrantLock(true);
示例
import java.util.concurrent.locks.ReentrantLock;
?
public class FairLockExample {
private static final ReentrantLock lock = new ReentrantLock(true);
?
public static void main(String[] args) {
Runnable task = () -> {
for (int i = 0; i < 2; i++) {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + " got the lock");
} finally {
lock.unlock();
}
}
};
?
Thread t1 = new Thread(task, "Thread-1");
Thread t2 = new Thread(task, "Thread-2");
Thread t3 = new Thread(task, "Thread-3");
?
t1.start();
t2.start();
t3.start();
}
}
運行結果通常會按照線程的啟動順序依次獲取鎖,例如:
Thread-1 got the lock
Thread-2 got the lock
Thread-3 got the lock
...
非公平鎖
非公平鎖(Non-Fair Lock)是默認的鎖實現,線程嘗試直接競爭鎖,不關注排隊順序。
特點
-
競爭機制:
-
每個線程都可以直接嘗試獲取鎖,成功則進入臨界區,失敗則進入等待隊列。
-
-
性能較高:
-
由于不需要維護嚴格的排隊順序,線程調度和喚醒的開銷較小,吞吐量更高。
-
-
可能導致線程饑餓:
-
某些線程可能長時間無法獲取鎖,因為新來的線程可能會插隊成功。
-
實現方式
在 Java 的 ReentrantLock 中,通過將構造方法的參數 fair 設置為 false 或默認值啟用非公平鎖:
ReentrantLock lock = new ReentrantLock(false);
示例
import java.util.concurrent.locks.ReentrantLock;
?
public class NonFairLockExample {
private static final ReentrantLock lock = new ReentrantLock();
?
public static void main(String[] args) {
Runnable task = () -> {
for (int i = 0; i < 2; i++) {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + " got the lock");
} finally {
lock.unlock();
}
}
};
?
Thread t1 = new Thread(task, "Thread-1");
Thread t2 = new Thread(task, "Thread-2");
Thread t3 = new Thread(task, "Thread-3");
?
t1.start();
t2.start();
t3.start();
}
}
運行結果可能會出現線程搶占的情況,例如:
Thread-1 got the lock
Thread-3 got the lock
Thread-2 got the lock
Thread-3 got the lock
...
公平鎖 vs 非公平鎖
| 特性 | 公平鎖 | 非公平鎖 |
|---|---|---|
| 鎖分配順序 | 按線程請求鎖的順序分配 | 隨機分配,允許插隊 |
| 線程饑餓 | 不會發生 | 可能發生 |
| 性能 | 性能較低,開銷較大 | 性能較高,吞吐量大 |
| 使用場景 | 需要嚴格控制線程公平性 | 更關注性能,允許一定的不公平性 |
選擇建議
-
使用公平鎖的場景:
-
需要避免線程饑餓,例如在多線程的資源分配中需要確保所有線程都能公平參與競爭。
-
-
使用非公平鎖的場景:
-
更注重性能,線程競爭較少時(如大部分操作鎖很快釋放),非公平鎖的性能優勢更明顯。
-
默認情況下,ReentrantLock

浙公網安備 33010602011771號