第一部分:Lock接口基础
理解Lock接口的核心功能与优势
学习目标
掌握Lock接口的核心方法、使用场景以及与synchronized的区别
synchronized的局限性
内置锁synchronized存在以下限制:
- 不可中断等待
- 不支持超时获取锁
- 无法实现公平锁
- 只能有一个等待队列
- 无法尝试获取锁
Lock接口的优势
Lock接口提供了更灵活的锁机制:
- 可中断锁获取
- 支持超时获取锁
- 可实现公平锁
- 多个条件队列
- 尝试获取锁机制
Lock接口方法 | 描述 | 使用场景 |
---|---|---|
lock() | 获取锁,如果锁不可用则阻塞 | 基本锁获取 |
unlock() | 释放锁 | 必须在finally块中调用 |
tryLock() | 尝试获取锁,立即返回结果 | 避免死锁 |
tryLock(long, TimeUnit) | 超时尝试获取锁 | 避免长时间阻塞 |
lockInterruptibly() | 可中断获取锁 | 响应中断 |
newCondition() | 创建新的Condition对象 | 实现精细等待/通知 |
Lock接口使用原则
1. 必须在try-finally块中使用Lock
2. 在try块前获取锁
3. 在finally块中释放锁
4. 避免在锁内调用外部方法
5. 使用tryLock避免死锁
第二部分:ReentrantLock使用
掌握ReentrantLock的基本使用和高级特性
学习目标
理解ReentrantLock的可重入性、公平锁和非公平锁的区别
基本使用示例
公平锁与非公平锁
ReentrantLock支持公平锁和非公平锁两种模式:
公平锁: 按照线程请求顺序获取锁
非公平锁: 允许插队,性能更高
tryLock使用示例
避免死锁和长时间阻塞:
第三部分:Condition应用
使用Condition实现精细的线程等待/通知机制
学习目标
掌握Condition接口的使用方法,实现生产者-消费者模式
Condition核心方法
- await() - 使当前线程等待
- signal() - 唤醒一个等待线程
- signalAll() - 唤醒所有等待线程
- awaitUninterruptibly() - 不可中断等待
- await(long, TimeUnit) - 超时等待
与Object监视器对比
- Condition可创建多个等待队列
- 更精细的线程控制
- 支持超时和中断
- 需要配合Lock使用
生产者-消费者模式实现
第四部分:读写锁
使用ReentrantReadWriteLock提高并发性能
学习目标
理解读写分离原理,掌握ReentrantReadWriteLock的使用
读写锁特性
- 读锁共享:多个线程可同时持有读锁
- 写锁独占:同一时间只有一个线程可持有写锁
- 写锁优先:写锁请求优先于读锁
- 锁降级:写锁可降级为读锁
适用场景
- 读多写少的场景
- 缓存系统
- 配置信息读取
- 资源池管理
缓存系统实现
第五部分:常见错误与陷阱
避免Lock使用中的常见问题
1. 忘记释放锁
未在finally块中释放锁导致死锁
正确做法:在finally块中释放锁
2. 锁嵌套问题
嵌套获取多个锁可能导致死锁
解决方案:按固定顺序获取锁
3. 条件等待错误
在条件等待前未检查条件
正确做法:使用while循环检查条件
4. 锁粒度过大
锁范围过大降低并发性能
解决方案:只锁真正需要同步的部分
5. 读写锁误用
在写操作中使用读锁
写操作必须使用写锁
6. 锁中断处理不当
未正确处理中断异常
正确做法:恢复中断状态或处理中断
第六部分:Lock最佳实践
高效、安全地使用Lock接口
Lock优点
- 更灵活的锁机制
- 支持中断和超时
- 可实现公平锁
- 多个条件队列
- 读写锁提高性能
Lock缺点
- 需要手动释放锁
- 使用不当容易死锁
- 代码复杂度增加
- 性能开销略大
最佳实践1:锁释放保证
- 始终在finally块中释放锁
- 避免在锁内抛出未处理异常
- 锁获取和释放配对使用
最佳实践2:避免死锁
- 使用tryLock避免死锁
- 按固定顺序获取多个锁
- 设置锁获取超时时间
最佳实践3:读写锁优化
- 读多写少场景使用读写锁
- 写锁降级提高性能
- 避免读锁升级为写锁
性能优化建议
1. 优先使用tryLock避免阻塞
2. 读写分离场景使用ReentrantReadWriteLock
3. 减少锁持有时间
4. 避免锁嵌套
5. 合理选择公平锁/非公平锁
第七部分:练习与测验
通过练习巩固Lock知识
动手练习
- 使用ReentrantLock实现线程安全的计数器
- 使用Condition实现生产者-消费者模式
- 使用ReentrantReadWriteLock实现缓存系统
- 使用tryLock解决转账死锁问题
Lock知识测验
深入学习资源
1. 《Java并发编程实战》第13章
2. Oracle官方文档:java.util.concurrent.locks
3. ReentrantLock源码分析
4. Java并发编程之美:Lock与Condition