核心概念
- 
Lock 接口 - 定义锁的基本操作:lock()、unlock()、tryLock()等。
- 替代 synchronized的显式锁机制,支持更细粒度的控制。
 
- 定义锁的基本操作:
- 
ReentrantLock(可重入锁) - 最常见的 Lock实现类,允许同一线程多次获取同一把锁(避免死锁)。
 
- 最常见的 
基本用法
            
            
              java
              
              
            
          
          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())javaif (lock.tryLock(1, TimeUnit.SECONDS)) { // 尝试在1秒内获取锁 try { // 临界区代码 } finally { lock.unlock(); } } else { // 超时处理 }
- 
公平锁 javaLock fairLock = new ReentrantLock(true); // 公平锁,按等待顺序分配锁
- 
条件变量 ( Condition)javaLock 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)
- 
适用于读多写少场景,提高并发性能: javaReadWriteLock 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,可以显著提升多线程程序的灵活性和性能。