面试题答案
一键面试功能特性
- ReentrantLock:
- 支持公平锁和非公平锁,通过构造函数参数控制,默认非公平锁。公平锁能保证等待时间最长的线程优先获取锁,减少线程饥饿。
- 提供了更灵活的锁获取方式,如
tryLock()
可尝试获取锁,获取不到立即返回;tryLock(long timeout, TimeUnit unit)
可在指定时间内尝试获取锁。 - 支持条件变量(Condition),可实现更精细的线程间协作,一个ReentrantLock可创建多个Condition实例。
- synchronized:
- 是非公平锁,无法实现公平锁机制。
- 锁获取方式比较单一,进入同步块或方法时获取锁,退出时释放锁。
- 线程协作依赖
wait()
、notify()
、notifyAll()
方法,这些方法依赖于对象监视器,功能相对简单。
性能表现
- ReentrantLock:在高并发且竞争激烈的场景下,非公平锁的性能通常优于
synchronized
,因为非公平锁减少了线程切换开销。在低竞争场景下,两者性能差异不大。 - synchronized:在Java 6之后进行了很多优化,如偏向锁、轻量级锁等,性能有了很大提升。在竞争不激烈时,性能表现良好。
锁的获取与释放方式
- ReentrantLock:通过
lock()
方法获取锁,需手动调用unlock()
方法释放锁,且unlock()
必须在try - finally
块中调用,以确保锁能正确释放,避免死锁。 - synchronized:进入同步代码块或方法时自动获取锁,退出同步代码块或方法时自动释放锁。
适用场景
- ReentrantLock:适用于需要更灵活的锁控制、公平锁机制、复杂线程协作的场景,如高并发下的任务调度系统。
- synchronized:适用于简单的线程同步场景,如方法同步、代码块同步,尤其是竞争不激烈的场景。
高并发环境下的选择
在高并发环境下,一个业务既要保证线程安全又要实现公平锁机制,优先选择ReentrantLock。原因是synchronized
无法实现公平锁机制,而ReentrantLock通过构造函数设置为公平锁,能满足业务对公平性的要求,同时其灵活的锁获取方式和条件变量机制,在高并发复杂业务场景下更具优势。