写在前面
锁是针对线程的,即只有线程才有锁的概念。
什么是可重入锁呢?
当一个线程获取了某个对象锁以后,还可以再次获得该对象锁。
什么时候我们会用到可重入锁呢?
1、demo
public class Demo1 {
public synchronized void functionA(){
System.out.println("iAmFunctionA");
functionB();
}
public synchronized void functionB(){
System.out.println("iAmFunctionB");
}
}
2、代码解释
functionA()和functionB()都是同步方法,当线程进入funcitonA()会获得该类的对象锁,这个锁"new Demo1()",在functionA()中调用了方法functionB(),但是functionB()也是同步的,因此该线程需要再次获得该对象锁(new Demo1())。其他线程是无法获该对象锁的。
这就是可重入锁。
作用
为了避免死锁,java中synchronized(修饰的对象、方法、代码块)和ReentrantLock都是可重入锁
扩展
1、重入锁的实现原理
通过为每个锁关联一个请求计数器和一个获得该锁的线程。当计数器为0时,认为锁是未被占用的。线程请求一个未被占用的锁时,JVM将记录该线程并将请求计数器设置为1,此时该线程就获得了锁,当该线程再次请求这个锁,计数器将递增,当线程退出同步方法或者同步代码块时,计数器将递减,当计数器为0时,线程就释放了该对象,其他线程才能获取该锁。
2、synchronized是锁?实现同步的原理是什么?
synchronized是java里的同于实现同步的关键字,它可以用于方法和代码块。Synchronized 的原理是,它会使用对象的内置锁(也称为监视器锁)来实现同步,每个对象都有一把内置锁,当一个线程访问一个同步代码块时,它会尝试获取这个锁,如果锁被其他线程持有,则该线程将被阻塞,直到锁被释放。
3、synchronized是用的实例内置锁还是class对象内置锁
修饰静态方法,修饰类,静态方法中的代码块,用的是class对象内置锁
修饰非静态方法,用的实例对象内置锁
修饰非静态方法中的代码块,可以用类对象也可以用实例对象的内置锁,但是非静态方法一般实例对象内置锁
public void f1(){
synchronized (this) {
System.out.println("true = " + true);
}
synchronized (Test06.class) {
System.out.println("true = " + true);
}
}