Java并发编程:ReentrantLock与ReentrantReadWriteLock深度解析

1 下载量 18 浏览量 更新于2024-09-01 收藏 103KB PDF 举报
本文主要介绍了Java并发编程中的JUC(Java Concurrency in Practice)知识点,特别是ReentrantLock和ReentrantReadWriteLock的源码解析。文章着重讲解了ReentrantLock的特性及其与synchronized关键字的不同之处。 ReentrantLock是Java并发包`java.util.concurrent.locks`中的一个类,它实现了Lock接口,提供了比`synchronized`更高级别的锁控制。ReentrantLock的主要特性包括: 1. 可重入性:持有锁的线程可以再次获取同一把锁,防止死锁。 2. 非阻塞尝试获取锁:`tryLock()`方法允许线程尝试获取锁,如果获取失败则立即返回。 3. 可中断的锁获取:`lockInterruptibly()`方法允许在等待锁的过程中响应中断,中断线程。 4. 超时获取锁:`tryLock(long timeout, TimeUnit unit)`允许设置等待时间,超过设定时间未获取到锁则返回。 ReentrantLock还引入了Condition对象,它与`synchronized`中`Object`的wait/notify方法有以下区别: - Condition的`await()`方法等同于`Object`的`wait()`,使线程等待特定条件。 - Condition的`signal()`方法等同于`Object`的`notify()`,唤醒一个等待线程。 - Condition的`signalAll()`方法等同于`Object`的`notifyAll()`,唤醒所有等待线程。 但是,ReentrantLock的Condition可以精确地唤醒匹配特定条件的线程,而`Object`的唤醒方式是随机的。 `tryLock()`、`lock()`和`lockInterruptibly()`之间的区别在于: - `tryLock()`:如果锁可用,则立即获取并返回`true`,否则立即返回`false`。 - `lock()`:如果锁不可用,会一直阻塞直到获取锁。 - `lockInterruptibly()`:与`lock()`类似,但当线程被中断时会抛出`InterruptedException`。 ReentrantLock与`synchronized`的区别: - 自动解锁:`synchronized`在异常发生时会自动释放锁,而ReentrantLock需要手动调用`unlock()`来解锁,这要求在`finally`块中进行解锁操作以确保释放锁,从而减少死锁的风险。 - 可中断性:ReentrantLock的`lockInterruptibly()`支持中断等待锁的线程,而`synchronized`不具备此功能。 - 公平性:ReentrantLock可以通过构造函数选择公平锁模式,保证等待最久的线程优先获取锁,而`synchronized`默认是非公平的。 - 更细粒度的控制:ReentrantLock提供了`Condition`,可以创建多个条件变量,实现更复杂的同步控制。 代码示例中,`MyService`类使用了ReentrantLock,展示了如何在业务逻辑中正确使用Lock,确保在finally块中释放锁。 ReentrantLock提供了一种更加灵活且强大的锁机制,适用于需要更细粒度控制、高并发以及需要避免死锁的场景。了解其特性和使用方式对于编写高效的并发代码至关重要。