java可重入锁是什么意思,java可重复锁,一篇文章让你彻底了解Java可重入锁和不可重入锁

java可重入锁是什么意思,java可重复锁,一篇文章让你彻底了解Java可重入锁和不可重入锁

最近在看Java ReentrantLock源代码,但是还是没有完全理解可重入和不可重入的概念。今天我特意整理了这篇文章,让你彻底了解Java重入锁和非重入锁。有需要的朋友可以参考一下。

可重入锁

广义的可重入锁是指可以重复递归调用的锁。锁在外层使用后,仍然可以在内层使用而不会死锁(前提是同一个对象或类)。这种锁被称为重入锁。

我的理解是,一个线程已经获取了某个锁,不需要等待就可以再次获取锁,不会出现死锁(当然不同的线程不能多次获取锁,需要等待)。

简单来说,一个线程获得一个锁,然后它可以再次获得锁,而无需等待,没有死锁。

常见的可重入锁

Synchronized和ReentrantLock是可重入锁。

可重入锁的释放

当同一个线程获得同一个锁时,状态值state将被累加。假设状态累积到2,锁每释放一次就减1。只有当状态值state减少到0时,其他线程才有机会获得锁。也就是说,国零就是已经解锁的标致。

可重入锁示例

公共类ReentrantTest实现Runnable {

@覆盖

公共无效运行(){

get();

}

公共同步void get() {

system . out . println(thread . current thread()。getName());

set();

}

/**

*递归方法

*/

公共同步空集(){

system . out . println(thread . current thread()。getName());

}

/**

*这里只有一个对象锁,就是rt对象的锁。

*当执行rt的get方法时,线程获取rt对象的锁。在get方法中执行set方法时,会再次请求rt对象的锁。因为synchronized是一个可重入的锁,所以它可以被再次获取。循环这个过程。

*假设不是重入锁,请求过程中会有阻塞,导致死锁。

* @param args

*/

公共静态void main(String[] args) {

reentrant test rt=new reentrant test();

//for(;)模拟无限循环

for(;){

新线程(rt)。start();

}

}

}

分析:这里只有一个对象锁,就是rt对象的锁。当执行rt的get方法时,线程获取rt对象的锁。在get方法中执行set方法时,会再次请求rt对象的锁。因为synchronized是一个可重入的锁,所以它可以被再次获取。循环这个过程。如果不是重入锁,请求过程中会有阻塞,导致死锁。

死锁

在多线程中,不同的线程在等待其他线程释放锁,而其他线程由于某种原因没有释放锁。程序运行受阻,无法正常运行或终止。

运行结果

Set()和get()同时输出同一个线程名,也就是说,一个线程执行时,不仅进入了set同步方法,还进入了get同步方法。使用递归同步时没有死锁,证明是可重入的。

可重入锁的实现原理?

每个锁都与一个线程保持器和一个计数器相关联。当计数器为0时,意味着锁没有被任何线程持有,因此任何线程都可能获得锁并调用相应的方法。当一个线程请求成功时,JVM将记下持有锁的线程,并将计数器设置为1;当其他线程请求锁时,它们必须等待。如果持有锁的线程再次请求锁,它可以再次获得锁,计数器将增加1;当线程退出同步代码块时,计数器将减1。如果计数器为0,锁将被释放。

让我们来分析上面这个可重入锁的例子。

递归调用同步代码块一次,计数器就会变成2。整个递归调用执行完后,先退出内层执行减1,再退出外层执行减1。然后松开锁。

不可重入锁

也就是一个线程已经获取了一个锁,然后不能再获取锁,就会被阻塞。

设计一个不可重入的锁。

公共类锁{

私有布尔值isLocked=false

/**

*锁定

*/

公共同步void锁()引发异常{

while(isLocked){

//当前线程释放锁,放弃CPU,进入等待状态,继续执行15行,直到被唤醒。

wait();

system . out . println(' wait ');

}

isLocked=true

}

/**

*解锁

*/

公共同步void unlock(){

isLocked=false

//唤醒一个等待的线程继续执行

notify();

}

}

测试

公共类测试{

Lock Lock=new Lock();

公共void print()引发异常{

//锁定标志为真

lock . lock();

//释放锁——等待它在第16行被阻塞

doAdd();

lock . unlock();

}

公共void doAdd()引发异常{

lock . lock();

system . out . println(' do add ');

lock . unlock();

}

公共静态void main(String[] args)引发异常{

测试Test=new Test();

test . print();

}

}

结果:虽然这里模拟的是不可重入锁,但实际上是在单线程环境中。当前线程执行print()方法,首先将标志锁定为true,然后释放锁——等待16行内阻塞的14行。在整个过程中,第一次进入锁同步方法,执行完成后,第二次进入锁同步方法,阻塞,等待。这个例子很好地说明了不可重入锁。

这就是本文对Java可重入锁和不可重入锁的全面理解。关于Java可重入锁和不可重入锁的更多信息,请搜索我们以前的文章或继续浏览下面的相关文章。希望你以后能支持我们!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: