实现可重入锁
今天突然想了解下 可重入锁,所以写一篇博客记录下,那么一个对象拿到锁后进入到方法后,还允许其他线程在进入吗?当不可能!那么我们来看下代码来模拟下可重入锁的场景。
此图可以看到方法enterA和enterB都有加锁的操作
看下此时的main方法调用了enterA和enterB方法 ,enterA方法进入后执行myLock.lock()拿到了锁,因为Lock(锁)对象是静态的所以这时调用enterB执行myLock.lock()时不会拿到锁而是进入wait(等待)状态,又因为程序是子上而下执行这时程序处于一种尴尬状态一直等待着释放锁,但此时又不是死锁,因为死锁是两条线程互相等待。
这时可重入锁发挥作用了!
/**
* 可重入锁
*/
public class MyReenTrantlock implements Lock {
//单例 添加volatile为了防止虚拟机指令重排
private static volatile MyReenTrantlock myReenTrantlock = null;
//当前对象是否获取到锁
private boolean lockStuta = false;
//记录当前是否一条线程
private Thread presentThread = null;
//记录可重入锁的数量
private int reenTrantlockNum = 0;
private MyReenTrantlock(){}
/**
* 判断该锁是否已被占用如果占用则让其等待
*/
@Override
public synchronized void lock() {
if(lockStuta && presentThread != Thread.currentThread()){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lockStuta = true;
presentThread = Thread.currentThread();
reenTrantlockNum++;
}
@Override
public void lockInterruptibly() throws InterruptedException {
}
@Override
public boolean tryLock() {
return false;
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return false;
}
@Override
public synchronized void unlock() {
if(presentThread == Thread.currentThread()){
//锁的数量减一
reenTrantlockNum--;
if(reenTrantlockNum == 0){
notify();
lockStuta = false;
}
}
}
@Override
public Condition newCondition() {
return null;
}
public static MyReenTrantlock getMyReenTrantlockBean(){
if(myReenTrantlock == null){
//双重检测锁
synchronized (MyReenTrantlock.class){
if(myReenTrantlock == null){
myReenTrantlock = new MyReenTrantlock();
}
}
}
return myReenTrantlock;
}
}
在执行my.lock()时会对当前线程进行记录,下次执行my.lock()时候就会进行判断,并对可重入锁数量进行记录,就不会导致一直等待现象,如果其他线程调用的话就会进入等待状态,直到锁被释放!
本人小白,如有错误请加以指正!
版权声明:本文为m1615404392原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。