Java面试高频考点——Synchronized关键字解析

Java面试高频考点——Synchronized关键字解析

问题一:JDK1.6之后Synchronized关键字做了哪些底层优化?

JDK1.6 对锁的实现引入了大量的优化,如偏向锁.轻量级锁.自旋锁.适应性自旋锁.锁消除.锁粗化

等技术来减少锁操作的开销。

锁主要存在四种状态,依次是:无锁状态.偏向锁状态.轻量级锁状态.重量级锁状态,他们会随着

竞争的激烈而逐渐升级。注意锁可以升级不可降级,这种策略是为了提高获得锁和释放锁的效率。

问题二:谈谈Synchronized和ReenTrantLock的区别?

(1) 两者都是可重入锁

两者都是可重入锁。“可重入锁”概念是:自己可以再次获取自己的内部锁。比如一个线程获得了

某个对象的锁,此时这个对象锁还没有释放,当其再次想要获取这个对象的锁的时候还是可以获取的,

如果不可锁重入的话,就会造成死锁。同一个线程每次获取锁,锁的计数器都自增 1,所以要等到锁的

计数器下降为 0 时才能释放锁。

(2) synchronized 依 赖 于 JVM 而 ReenTrantLock 依 赖 于 API

synchronized 是依赖于 JVM 实现的,前面我们也讲到了 虚拟机团队在 JDK1.6 为

synchronized 关键字进行了很多优化,但是这些优化都是在虚拟机层面实现的,并没有直接暴露给

我们。ReenTrantLock 是 JDK 层面实现的(也就是 API 层面,需要 lock() 和 unlock 方法配合

try/fifinally 语句块来完成),所以我们可以通过查看它的源代码,来看它是如何实现的。

(3)ReenTrantLock 比 synchronized 增加了一些高级功能

相比 synchronized,ReenTrantLock 增加了一些高级功能。主要来说主要有三点:等待可中断;

可实现公平锁; 可实现选择性通知(锁可以绑定多个条件)ReenTrantLock 提供了一种能够中断

等待锁的线程的机制,通过 lock.lockInterruptibly()来实现这个机制。也就是说正在等待的线程可以

选择放弃等待,改为处理其他事情。

ReenTrantLock 可以指定是公平锁还是非公平锁。而 synchronized 只能是非公平锁。所谓的

公平锁就是先等待的线程先获得锁。 ReenTrantLock 默认情况是非公平的,可以通过

ReenTrantLock 类的 ReentrantLock(boolean fair) 构造方法来制定是否是公平的。synchronized 关

键字与 wait()和 notify/notifyAll()方法相结合可以实现等待/通知机制,ReentrantLock 类当然也 可

以实现,但是需要借助于 Condition 接口与 newCondition() 方法。Condition 是 JDK1.5 之后才有

的,它具有很 好的灵活性,比如可以实现多路通知功能也就是在一个 Lock 对象中可以创建多个 Condition 实

例(即对象监视器),线程对象可以注册在指定的 Condition 中,从而可以有选择性的进行线程通

知,在调度线程上更加灵活。 在使用 notify/notifyAll()方法进行通知时,被通知的线程是由 JVM

选择的,用ReentrantLock 类结合 Condition 实例可以实现“选择性通知” ,这个功能非常重要,

而且是 Condition 接口默认提供的。而 synchronized 关键字就相当于整个 Lock 对象中只有一个

Condition 实例,所有的线程都注册在它一个身上。如果执行 notifyAll()方法的话就会通知所有处于

等待状态的线程这样会造成很大的效率问题,而 Condition 实例的 signalAll()方法 只会唤醒注册在

该 Condition 实例中的所有等待线程。如果你想使用上述功能,那么选择 ReenTrantLock 是一个不

错的选择。

小编会经常分享一些Java高频面试题,供大家去为自己充能,希望和大家一起进步!!!

经验分享 程序员 微信小程序 职场和发展