可重入锁(递归锁)
可重入锁(递归锁)
是什么?
同一线程外层函数在获得锁之后,内层函数仍然能获取该锁的代码
同一线程在外层方法获取锁的时候,在进入内层方***自动获取锁
即线程可以进入任何一个它已经拥有的锁 所同步着的代码块。
必须是同一把锁
好处:
可以在一定程度上避免死锁。
public class juc1 extends Thread{ public static void main(String[] args) { juc1 juc1 = new juc1(); Thread t1 = new Thread(juc1,"t1"); t1.start(); } @Override public void run() { say(); } public synchronized void say(){ System.out.println((Thread.currentThread().getName() + "\tsay..")); get(); //外层方法可以进入 内层同步着的代码块 (get) } public synchronized void get(){ System.out.println(Thread.currentThread().getName()+"\tget.."); } }
如上实例:可重入锁 指的就是:在获取到say()的锁后,say()方法可以获取到上着锁的get()方法。
为什么Synchronized 是可重入锁,底层是怎么实现的?
每个锁对象都持有一个锁计数器,和一个指向持有该锁的线程的指针。
当monitorenter,如果目标对象计数器为0,那么说明他没有被其他线程持有,JAVA虚拟机会将该锁对象持有的线程设为该线程,并将计数器加1。
在目标对象的计数器不为0的情况下,如果锁对象的持有线程是当前线程,那么java虚拟机可以将计数器加1,否则需要等待,直至持有的线程释放锁。
执行monitorexit时,java虚拟机将计数器减1,计数器为0表示锁已经被释放。