Lock锁
核心概念
-  Lock 接口 - 定义锁的基本操作:lock()、unlock()、tryLock()等。
- 替代 synchronized的显式锁机制,支持更细粒度的控制。
 
- 定义锁的基本操作:
-  ReentrantLock(可重入锁) - 最常见的 Lock实现类,允许同一线程多次获取同一把锁(避免死锁)。
 
- 最常见的 
基本用法
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class LockExample {private final Lock lock = new ReentrantLock();private int counter = 0;public void increment() {lock.lock(); // 获取锁try {counter++;} finally {lock.unlock(); // 确保释放锁}}
}
Lock 与 synchronized 的区别
1. 实现方式
-  synchronized- JVM 内置关键字:通过对象头的锁状态(偏向锁→轻量级锁→重量级锁)实现,由 JVM 自动管理。
- 隐式加锁:无需手动释放锁,代码块或方法执行完毕自动释放。
 
-  Lock- Java API 接口(如 ReentrantLock):基于AQS(AbstractQueuedSynchronizer)实现,需显式调用lock()和unlock()。
- 显式加锁:必须手动释放锁(通常放在 finally块中),否则可能导致死锁。
 
- Java API 接口(如 
2. 锁特性
| 特性 | synchronized | Lock | 
|---|---|---|
| 公平性 | 仅支持非公平锁 | 支持公平锁和非公平锁(构造参数指定) | 
| 中断响应 | 不支持中断等待线程 | 支持 lockInterruptibly()中断等待 | 
| 超时机制 | 不支持 | 支持 tryLock(timeout)设定超时时间 | 
| 条件变量 | 单一条件( wait()/notify()) | 支持多个 Condition对象,精细化线程唤醒 | 
| 锁状态查询 | 无法判断锁是否被占用 | 支持 isLocked()等方法查询锁状态 | 
3. 性能差异
- 低竞争场景:
 synchronized性能更优(JVM 的偏向锁、轻量级锁优化减少开销)。
- 高竞争场景:
 Lock性能更好(基于 CAS 自旋减少线程阻塞,支持更细粒度的锁控制)。
4. 锁类型
- 均为悲观锁:
 两者都假设并发冲突必然发生,访问共享资源前先加锁(synchronized直接阻塞,Lock可能自旋后阻塞)。
- 乐观锁 是另一种机制(如 CAS或版本号),无需加锁,通过冲突检测实现线程安全。
5. 使用场景
-  优先 synchronized:- 简单同步需求(如单例模式、简单代码块)。
- 低线程竞争场景(利用 JVM 锁优化)。
 
-  优先 Lock:- 需要复杂控制(如超时、中断、公平锁)。
- 高并发场景(减少线程阻塞,提升吞吐量)。
- 需要绑定多个条件变量(如生产者-消费者模型)。
 
总结
- synchronized:简单、自动管理,适合基础同步需求。
- Lock:灵活、功能强大,适合高并发和复杂场景。
- 选择依据:优先 synchronized,复杂需求或性能瓶颈时改用Lock。
高级功能
-  尝试获取锁 ( tryLock())if (lock.tryLock(1, TimeUnit.SECONDS)) { // 尝试在1秒内获取锁try {// 临界区代码} finally {lock.unlock();} } else {// 超时处理 }
-  公平锁 Lock fairLock = new ReentrantLock(true); // 公平锁,按等待顺序分配锁
-  条件变量 ( Condition)Lock lock = new ReentrantLock(); Condition condition = lock.newCondition();// 线程等待条件 lock.lock(); try {condition.await(); // 释放锁并等待,类似 wait() } finally {lock.unlock(); }// 唤醒等待线程 lock.lock(); try {condition.signal(); // 类似 notify() } finally {lock.unlock(); }
读写锁 (ReentrantReadWriteLock)
-  适用于读多写少场景,提高并发性能: ReadWriteLock rwLock = new ReentrantReadWriteLock(); Lock readLock = rwLock.readLock(); // 读锁(共享) Lock writeLock = rwLock.writeLock(); // 写锁(独占)public void readData() {readLock.lock();try {// 读操作} finally {readLock.unlock();} }public void writeData() {writeLock.lock();try {// 写操作} finally {writeLock.unlock();} }
注意事项
- 必须在 finally中释放锁:避免因异常导致锁无法释放。
- 避免死锁:确保锁的获取和释放顺序一致。
- 性能考量:高竞争场景下,synchronized经过 JVM 优化后性能接近Lock,但Lock提供更多控制选项。
适用场景
- 需要细粒度控制锁(如超时、可中断)。
- 需要公平锁或读写锁。
- 需要多个条件变量实现复杂线程协作。
通过合理使用 Lock,可以显著提升多线程程序的灵活性和性能。
