ReentrantLock是獨占可重入鎖,所謂重入鎖,指的是以線程為單位,當一個線程獲取對象鎖之后,這個線程可以再次獲取本對象上的鎖,而其他的線程是不可以的。
synchronized 和 ReentrantLock 都是可重入鎖。
可重入鎖的意義在于防止死鎖。
實現(xiàn)原理是通過為每個鎖關聯(lián)一個請求計數(shù)器和一個占有它的線程。當計數(shù)為0時,認為鎖是未被占有的;線程請求一個未被占有的鎖時,JVM將記錄鎖的占有者,并且將請求計數(shù)器置為1 。
如果同一個線程再次請求這個鎖,計數(shù)將遞增;
每次占用線程退出同步塊,計數(shù)器值將遞減。直到計數(shù)器為0,鎖被釋放。
使用ReentrantLock可實現(xiàn)公平鎖與非公平鎖。
公平鎖:多個線程按照申請鎖的順序去獲得鎖,線程會直接進入隊列去排隊,永遠都是隊列的第一位才能得到鎖。
優(yōu)點:所有的線程都能得到資源。
缺點:吞吐量會下降很多,隊列里面除了第一個線程,其他的線程都會阻塞,cpu喚醒阻塞線程的開銷會很大。
非公平鎖:多個線程去獲取鎖的時候,會直接去嘗試獲取,獲取不到,再去進入等待隊列,如果能獲取到,就直接獲取到鎖。
優(yōu)點:可以減少CPU喚醒線程的開銷,整體的吞吐效率會高點,CPU也不必取喚醒所有線程,會減少喚起線程的數(shù)量。
缺點:可能導致隊列中間的線程一直獲取不到鎖或者長時間獲取不到鎖。
代碼如下:
package com.example.multithread.ReentrantLock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author liujy
* @description 可重入鎖實現(xiàn)公平鎖與非公平鎖
* @since 2020-12-29 11:03
*/
public class ReentrantLockTest {
// Lock lock = new ReentrantLock();默認實現(xiàn)的是非公平鎖
// 非公平鎖
// private static Lock lock = new ReentrantLock(false);
// 公平鎖
private static Lock lock = new ReentrantLock(true);
public static void test() {
for (int i = 0; i < 2; i++) {
try {
lock.lock();
System.out.println(Thread.currentThread().getName() + " get lock");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
// System.out.println(Thread.currentThread().getName() + " release lock");
}
}
}
public static void main(String[] args) {
new Thread(() -> test(), "kacey").start();
new Thread(() -> test(), "maria").start();
new Thread(() -> test(), "tom").start();
new Thread(() -> test(), "chris").start();
}
}
公平鎖運行結果如下:
kacey get lock
maria get lock
tom get lock
chris get lock
kacey get lock
maria get lock
tom get lock
chris get lock
非公平鎖運行結果如下:
kacey get lock
kacey get lock
maria get lock
maria get lock
tom get lock
tom get lock
chris get lock
chris get lock