JUC-可重入锁和不可重入锁

不可重入锁🔒

锁代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Lock{
private boolean isLocked = false;
public synchronized void lock() throws InterruptedException{
while(isLocked){
wait();//把当前线程wait
}
isLocked = true;
}
public synchronized void unlock(){
isLocked = false;
notify();
}
}

应用示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Count{
Lock lock = new Lock();
public void A(){
lock.lock();
B();
lock.unlock();
}
public void B(){
lock.lock();
//do something
lock.unlock();
}
}

当A中调用B方法时,获得了锁,这时就无法再调用B方法,必须先释放锁才能调用,B也会被阻塞从而造成死锁。称这种锁为不可重入锁,也叫自旋锁。


可重入锁🔒

锁代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Lock{
boolean isLocked = false;
Thread lockedBy = null;
int lockedCount = 0;
public synchronized void lock()
throws InterruptedException{
Thread thread = Thread.currentThread();
while(isLocked && lockedBy != thread){
wait();
}
isLocked = true;
lockedCount++;
lockedBy = thread;
}
public synchronized void unlock(){
if(Thread.currentThread() == this.lockedBy){
lockedCount--;
if(lockedCount == 0){//获得该锁的那个线程,获得了多少次该锁(即调用了几次lock方法,即重入了几次),就得unlock几次,即lockedCount=0,才会把那些wait(阻塞)的线程唤醒
isLocked = false;
notify();
}
}
}
}

可重入锁与不可重入锁对比,简单来说就是可重入锁会多两个属性:

  • 获得该锁的线程

  • 获得该锁的次数

根据第一个属性判断,如果是持有该锁的那个线程又来lock,不会被阻塞(wait),而是在上锁的次数加一(表示这个线程又锁了一次(重入)),只有该线程unlock的次数达到上锁的次数(即第二个属性等于0),才会唤醒其他线程。**

java中常用的可重入锁:

  • synchronized

  • java.util.concurrent.locks.ReentrantLock

文章作者: GeYu
文章链接: https://nuistgy.github.io/2023/03/22/JUC-可重入and不可重入锁/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Yu's Blog