大家好,又見面了,我是你們的朋友全棧君。
不可重入鎖示例( 同一個線程不可以重入上鎖後的代碼段
)
同一個線程不可以重入上鎖後的代碼段
如下是一個不可重入鎖的邏輯過程,會發現執行main方法控制台會列印
執行doJob方法前
,然後就會一直線程阻塞,不會列印
執行doJob方法過程中
,原因在于第一次上鎖後,由于沒有釋放鎖,是以執行第一次lock後
isLocked = true
,這個時候調用
doJob()
内部又一次調用了
lock()
由于上個線程将
isLocked = true
,導緻再次進入的時候就進入死循環。導緻線程無法執行
System.out.println("執行doJob方法過程中");
這行代碼,是以控制台隻能列印
執行doJob方法前
。這種現象就造成了不可重入鎖
public class Count{
MyLock lock = new MyLock();
public static void main(String[] args) throws InterruptedException {
new Count().doSomeThing(); // 示例的main方法
}
public void doSomeThing() throws InterruptedException {
lock.lock(); // 第一次上鎖
System.out.println("執行doJob方法前");
doJob(); // 方法内會再次上鎖
lock.unlock(); // 釋放第一次上的鎖
}
public void doJob() throws InterruptedException {
lock.lock();
System.out.println("執行doJob方法過程中");
lock.unlock();
}
}
/** * 自定義鎖 */
class MyLock{
private boolean isLocked = false;
public synchronized void lock() throws InterruptedException{
while(isLocked){
wait();
}
isLocked = true; // 線程第一次進入後就會将器設定為true,第二次進入是就會由于where true進入死循環
}
public synchronized void unlock(){
isLocked = false; // 将這個值設定為false目的是釋放鎖
notify(); // 接觸阻塞
}
}
複制
可重入鎖示例( 同一個線程可以重入上鎖的代碼段,不同的線程則需要進行阻塞
)
同一個線程可以重入上鎖的代碼段,不同的線程則需要進行阻塞
java的可重入鎖有:
ReentrantLock(顯式的可重入鎖)
、
synchronized(隐式的可重入鎖)
可重入鎖誕生的目的就是防止上面不可重入鎖的那種情況,導緻同一個線程不可重入上鎖代碼段。
目的就是讓同一個線程可以重新進入上鎖代碼段。
設計可重入鎖的示例代碼
public class MyReentrantLock {
boolean isLocked = false; // 預設沒有上鎖
Thread lockedBy = null; // 記錄阻塞線程
int lockedCount = 0; // 上鎖次數計數
/** * 上鎖邏輯 */
public synchronized void lock() throws InterruptedException {
Thread thread = Thread.currentThread();
// 上鎖了 并且 如果是同一個線程則放行,否則其它線程需要進入where循環進行等待
while (isLocked && lockedBy != thread) {
wait();
}
isLocked = true; // 第一次進入就進行上鎖
lockedCount++; // 上鎖次數計數
lockedBy = thread; // 目前阻塞的線程
}
/** * 釋放鎖邏輯 */
public synchronized void unlock() {
if (Thread.currentThread() == this.lockedBy) {
lockedCount--; // 将上鎖次數減一
if (lockedCount == 0) {
// 當計數為0,說明所有線程都釋放了鎖
isLocked = false; // 真正的将釋放了所有鎖
notify();
}
}
}
}
複制
釋出者:全棧程式員棧長,轉載請注明出處:https://javaforall.cn/153260.html原文連結:https://javaforall.cn