概念
意思是当同一个线程的outer方法获取锁时,进入线程的inner方法会自动获取锁(前提是锁对象必须是同一个对象),不会因为之前已经获取过而阻塞并没有被释放。即一个线程中的多个进程可以获取同一个锁,持有这个同步锁可以再次进入
可重入锁类型1. 隐式锁
默认情况下,隐式锁(即同步关键字使用的锁)是可重入锁。当一个同步修改的方法或代码块调用该类的其他同步修改的方法或代码块时,总是可以获得锁
代码示例
static Object objectLock = new Object();
//同步代码块,持有同一把锁
@Test
public void m1() {
new Thread(() -> {
synchronized (objectLock) {
System.out.println("------外层");
synchronized (objectLock) {
System.out.println("------中层");
synchronized (objectLock) {
System.out.println("------内层");
}
}
}
}, "t1").start();
}
Synchronized的重入实现机制?
每个锁对象都有一个锁计数器和一个指向持有锁的线程的指针。在执行monitorenter时,如果目标锁对象的计数器为零,则表示它没有被其他线程持有。Java虚拟机将持有锁对象的线程设置为当前线程,并将其计数器加1。在目标锁对象的计数器不为零的情况下,如果持有锁对象的线程是当前线程,则Java虚拟机可以将其计数器加1同步代码块的锁是什么,否则需要等到持有锁的线程释放锁。在执行monitorexit时同步代码块的锁是什么,Java虚拟机需要将锁对象的计数器减1。计数器为零表示锁已被释放。
2. 显式锁
显式锁(即Lock)也有ReentrantLock等可重入锁
代码示例
public static void main(String[] args) {
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
//一定要加锁几次就解锁几次,否则解锁不干净,会影响其他线程的锁
new Thread(() -> {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + "-----外层");
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + "-----中层");
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + "-----外层");
} finally {
lock.unlock();
}
} finally {
lock.unlock();
}
} finally {
lock.unlock();
}
}, "t1").start();
}
注意:加锁后必须多次解锁,否则解锁不干净,会影响其他线程的锁
© 版权声明
THE END
喜欢就支持一下吧
请登录后发表评论
注册
社交帐号登录